Профилирование – это очень важный аспект при разработке и поддержке почти любого приложения. Не в меньшей мере это относится и к базам данных. Особенно при больших объёмах информации производительность запросов к хранилищу данных является очень критичным. Что же касается производительности запросов в 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 имеет графический профайлер во встроенной консоли что делает процесс анализа более простым и удобным для небольших задач и в процессе разработки.
Автор: SleepwalkerOne