Pull to refresh

Profiler в MarkLogic Server

Reading time5 min
Views1.4K
Профилирование – это очень важный аспект при разработке и поддержке почти любого приложения. Не в меньшей мере это относится и к базам данных. Особенно при больших объёмах информации производительность запросов к хранилищу данных является очень критичным. Что же касается производительности запросов в MarkLogic Server и их профилирования, можно сказать что эти вопросы являются одними из самых важных так как XQuery используемый в MarkLogic Server позволяет писать не только очень сложные запросы к самой DB но и довольно сложные приложения.

В MarkLogic Server есть достаточно хороший функционал профилирования представленный в десяти встроенных функциях. Все они располагаются в пространстве имен “http://marklogic.com/xdmp/profile“ и доступны с префиксом “prof:

prof:eval(
   $xquery as xs:string,
   [$vars as item()*],
   [$options as node()?]
) as item()*


Этой функции передается XQuery в виде текстовой строки производительность которого стоит протестировать.

prof:eval( "1 + 1" )


Возвращаемым значением для prof:eval является последовательность (<XML с отчетом>, <результат выполнения XQuery>). Отчет содержит достаточно подробную информацию о выполнении XQuery.

Пример

<prof:metadata>
      <prof:overall-elapsed>PT0S</prof:overall-elapsed>
      <prof:created>2013-09-13T00:00:00.000+04:00</prof:created>
      <prof:server-version>6.0-3</prof:server-version>
    </prof:metadata>
    <prof:histogram>
      <prof:expression>
	<prof:expr-id>13367197075475374717</prof:expr-id>
	<prof:expr-source>1 + 1</prof:expr-source>
	<prof:uri/>
	<prof:line>1</prof:line>
	<prof:column>33</prof:column>
	<prof:count>1</prof:count>
	<prof:shallow-time>PT0S</prof:shallow-time>
	<prof:deep-time>PT0S</prof:deep-time>
      </prof:expression>
    </prof:histogram>
  </prof:report>,
  2


Стоить заметить, что передаваемый таким образом XQuery никак не связан с контекстом в котором выполняется prof:eval. Для того чтобы передать параметры в отлаживаемый XQuery можно воспользоваться параметром $vars, который представляет из себя последовательность переменных в виде (QName, <значение>). Пример

prof:eval(
	"declare variable $a external; $a + 1",
	(fn:QName("", "a"), 1) 
)


или так

prof:eval( 
  "declare variable $a external; declare variable $b external; $a + $b",   
  (fn:QName("", "a"), 1, fn:QName("", "b"), 1)
)


Если при выполнении XQuery происходит ошибка то prof:eval выкидывает исключение PROF-PROFILEALLOW.

Про следующую функцию можно сказать, что она аналогична prof:eval за тем лишь исключением, что на вход она принимает не XQuery в виде текстовой строки, а путь к XQuery модулю.

prof:invoke(
   $path as xs:string,
   [$vars as item()*],
   [$options as node()?]
) as item()*


XQuery модуль не должен быть библиотекой, он должен быть “главным” исполняемым модулем. Путь к модулю резолвится относительно корня application server’а. А в остальном prof:invoke полностью аналогична prof:eval.

MarkLogic Server позволяет создавать профили не только для XQuery переданного в функции prof:eval и prof:invoke, но и для инструкций находящихся непосредственно в модуле программы. Причем, профилирование привязано не к конкретному коду программы а к запросу обрабатываемому сервером. Это позволяет отлаживать не только код в текущем запросе, но и производить анализ любого запроса зная его ID и не вмешиваясь в код приложения, что может быть очень полезным в случает анализа приложения в продакшн середе.

Для того чтобы начать сбор информации о выполнении нужно вызвать функцию

prof:enable(
   $request-id as xs:unsignedLong
) as empty-sequence()


Где $request-id идентификатор запроса для которого следует начать профилирование.
Получить ID текущего запроса можно функцией xdmp:request().
Для того чтобы остановить сбор информации нужно воспользоваться функцией

prof:disable(
   $request-id as xs:unsignedLong
) as empty-sequence()


Как следует из вышесказанного профилировать можно любой код обрабатываемый между вызовами функций prof:enable и prof:disable если профилирование выполняется для текущего запроса, либо между моментами времени к которые вызывались эти функции если производится анализ не текущего запроса.

При попытке использовать профайлер проверяется наличие следующих прав пользователя
“http://marklogic.com/xdmp/privileges/profile-my-requests” – для профилирования своих запросов
“http://marklogic.com/xdmp/privileges/profile-any-requests” – для профилирования любых запросов
Конечно же есть и маленькое исключение – для профилирования текущего запроса (запроса к котором находятся функции профилирования) не требуется специальных привидений, а “profile-my-requests” дает право на профайлинг всех (исключая текущий) запросов текущего пользователя.
Для проверки доступно ли профилирование для определенного запроса можно воспользоваться функцией

prof:allowed(
   $request-id as xs:unsignedLong
) as xs:boolean


Для того чтобы получить собранную информацию о выполнении запроса следует воспользоваться функцией

prof:report(
   $request-id as xs:unsignedLong
) as element(prof:report)?


В отличии от prof:eval, которая возвращает отчет и результат выполнения XQuery функции prof:report возвращает только отчет.

Пример использования prof:report

let $e as empty-sequence() := prof:enable( xdmp:request() )
let $r as xs:string := fn:string( 1 + 2 )
return
    prof:report( xdmp:request() )


Иногда возникает необходимость удалить накопленную информацию и начать вести отчет заново, для этого используется функция

prof:reset(
   $request-id as xs:unsignedLong
) as empty-sequence()


Следующая функция аналогична функции prof:eval, но в отличии от неё prof:value наследует контекст при выполнении указанного XQuery

prof:value(
   $expr as xs:string
) as item()*


Наследование контекста функцией prof:value позволяет писать такой код

let $a := 1
let $b := 2
return 
    prof:value('$a + $b')


Существует еще две интересные функции

prof:xslt-eval(
   $stylesheet as element(),
   $input as node()?,
   [$params as map:map?],
   [$options as node()?]
) as item()*


prof:xslt-invoke(
   $path as xs:string,
   $input as node()?,
   [$params as map:map?],
   [$options as node()?]
) as item()*


Где $input – это XML документ, обрабатываемый в XSLT процессоре.
Из названия этих функций понятно что они аналогичны функциям prof:eval и prof:invoke, но используются для профилирования XSLT, процессор которого разработчики MarkLogic Server так заботливо встроили в свой продукт.

MarkLogiс Server предоставляет достаточно мощные средства для анализа производительности. С помшью этого механизма можно создавать сложные профайлеры для разнообразных задач. Вместе с тем MarkLogiс Server имеет графический профайлер во встроенной консоли что делает процесс анализа более простым и удобным для небольших задач и в процессе разработки.
Tags:
Hubs:
+3
Comments0

Articles