Рекомендации по язык запросов Kusto запросам

Ниже приведены некоторые рекомендации, которые позволят ускорить выполнение запроса.

Короче говоря,

Действие Назначение Не используйте Примечания
Уменьшение объема запрашиваемых данных Используйте такие механизмы, как оператор , where чтобы уменьшить объем обрабатываемых данных. Ниже приведены эффективные способы уменьшения объема обрабатываемых данных.
Избегайте использования избыточных полных ссылок При ссылке на локальные сущности используйте непроверенное имя. Дополнительные сведения по этому вопросу см. ниже.
datetime Столбцы datetime Используйте тип данных . Не используйте long тип данных. В запросах не используйте функции преобразования времени Unix, такие как unixtime_milliseconds_todatetime(). Вместо этого используйте политики обновления для преобразования времени UNIX в datetime тип данных во время приема.
Строковые операторы Используйте оператор has. Не используйте contains. При поиске полных токенов лучше использовать метод has, поскольку он не ищет подстроки.
Операторы с учетом регистра Используйте ==. Не используйте =~. При возможности используйте операторы с учетом регистра.
Используйте in. Не используйте in~.
Используйте contains_cs. Не используйте contains. Если вы можете использовать has/has_cs, а не contains/contains_cs, это даже лучше.
Поиск текста Поиск в определенном столбце Не используйте *. * выполняет полнотекстовый поиск по всем столбцам.
Извлечение полей из динамических объектов в миллионах строк Материализуйте столбец во время приема, если большинство запросов приводят к извлечению полей из динамических объектов в миллионах строк. Таким образом, вы будете платить лишь за одно извлечение данных из столбца.
Поиск редких ключей и значений в динамических объектах Используйте MyTable | where DynamicColumn has "Rare value" | where DynamicColumn.SomeKey == "Rare value". Не используйте MyTable | where DynamicColumn.SomeKey == "Rare value". Таким образом, вы отфильтруете большинство записей и выполните синтаксический анализ JSON только для оставшихся записей.
Оператор let со значением, которое используется более одного раза Используйте функцию materialize(). Дополнительные сведения об использовании функции materialize()см. здесь. Дополнительные сведения см. в статье Оптимизация запросов, использующих именованные выражения.
Применение преобразований к более чем 1 миллиарду записей Измените область запроса, чтобы уменьшить объем данных, поступающих в преобразование. Не преобразовывайте большие объемы данных, если их можно опустить.
Новые запросы Используйте limit [small number] или count в конце. Выполнение несвязанных запросов к неизвестным наборам данных может привести к возврату клиенту гигабитных результатов, что приведет к медленному отклику и переполнению кластера.
Cравнения с учетом регистра Используйте Col =~ "lowercasestring". Не используйте tolower(Col) == "lowercasestring".
Сравнение данных, которые уже находятся в нижнем регистре (или в верхнем регистре) Col == "lowercasestring" (или Col == "UPPERCASESTRING") Старайтесь не использовать сравнения без учета регистра.
Фильтрация по столбцам Фильтруйте по столбцу таблицы. Не фильтруйте по вычисляемому столбцу.
Используйте T | where predicate(*Expression*). Не используйте T | extend _value = *Expression* | where predicate(_value).
Оператор summarize Используйте hint.shufflekey=<key> , если group by keys оператор summarize имеет высокую кратность. Высокая кратность в идеале превышает 1 миллион.
Оператор join Выберите первой таблицу с меньшим количеством строк (самая левая в запросе).
Используйте in вместо левого полусового join значения для фильтрации по одному столбцу.
Соединение между кластерами Во всех кластерах выполните запрос на "правой" стороне соединения, где находится большинство данных.
Соединение, если левая часть маленькая, а правая большая Используйте hint.strategy=broadcast. Малый означает до 100 МБ данных.
Соединение, если правая сторона мала, а левая сторона — большая Используйте оператор подстановкиjoin вместо оператора Если правая часть поиска превышает несколько десятков МБ, запрос завершится ошибкой.
Соединение, если обе стороны слишком большие Использование hint.shufflekey=<key> Используется, когда ключ соединения имеет высокую кратность.
Извлечение значений в столбце, которые имеют общий формат или шаблон строк Используйте оператор parse. Не используйте несколько операторов extract(). Например, значения вроде "Time = <time>, ResourceId = <resourceId>, Duration = <duration>, ...."
Функция extract() Используйте, если проанализированные строки не принадлежат к одному и тому же формату или шаблону. Извлеките необходимые значения с помощью регулярного выражения.
Функция materialize() . Отправка всех возможных операторов, которые позволят сократить материализованный набор данных и сохранить семантику запроса. Например, фильтры или столбцы, которые нужны только для проекта. Дополнительные сведения см. в статье Оптимизация запросов, использующих именованные выражения.
Использование материализованных представлений Используйте материализованные представления для хранения часто используемых агрегатов. Предпочитать использовать функцию materialized_view() для запроса только материализованной части materialized_view('MV')

Уменьшение объема обрабатываемых данных

Производительность запроса напрямую зависит от объема данных, необходимых для обработки. Чем меньше данных обрабатывается, тем быстрее выполняется запрос (и тем меньше ресурсов он потребляет). Поэтому наиболее важной рекомендацией является структурирование запроса таким образом, чтобы уменьшить объем обрабатываемых данных.

Примечание

В приведенном ниже обсуждении важно иметь в виду концепцию избирательности фильтров. Избирательность — это то, какой процент записей отфильтровывается при фильтрации по определенному предикату. Высокоизбирательный предикат означает, что после применения предиката остается только несколько записей, что сокращает объем данных, которые необходимо затем эффективно обрабатывать.

В порядке важности:

  • Ссылаются только на таблицы, данные которых требуются запросу. Например, при использовании union оператора со ссылками на таблицы с подстановочными знаками лучше с точки зрения производительности ссылаться только на несколько таблиц, а не использовать подстановочный знак (*) для ссылки на все таблицы, а затем отфильтровать данные с помощью предиката по имени исходной таблицы.

  • Воспользуйтесь преимуществами область данных таблицы, если запрос относится только к определенному область. Функция table() предоставляет эффективный способ устранения данных путем их определения области в соответствии с политикой кэширования (параметр DataScope).

  • Примените where оператор запроса сразу после ссылок на таблицы.

  • При использовании where оператора запроса разумное использование порядка предикатов (в одном операторе или с несколькими последовательными операторами не имеет значения), может существенно повлиять на производительность запроса, как описано ниже.

  • Сначала примените предикаты с целым сегментом. Это означает, что в первую очередь следует применять предикаты, использующие функцию extent_id(), как и предикаты, использующие функцию extent_tags(), и предикаты, которые очень выборочно относятся к секциям данных таблицы (если они определены).

  • Затем примените предикаты, которые действуют на datetime столбцы таблицы. Kusto включает очень эффективный индекс для таких столбцов, часто полностью устраняя сегменты данных без необходимости доступа к этим сегментам.

  • Затем примените предикаты, которые действуют на string столбцы и dynamic , особенно такие предикаты, которые применяются на уровне термина. Предикаты должны быть упорядочены по избирательности (например, поиск идентификатора пользователя при наличии миллионов пользователей является очень избирательным и обычно является поиском термина, для которого индекс очень эффективен).

  • Затем примените предикаты, которые являются выборочными и основаны на числовых столбцах.

  • Наконец, для запросов, которые сканируют данные столбца таблицы (например, для предикатов, таких как "содержит "@!@!", которые не имеют терминов и не получают преимуществ от индексирования), упорядочение предикатов таким образом, чтобы те, которые сканируют столбцы с меньшим объемом данных, были первыми. Это уменьшает необходимость распаковки и сканирования больших столбцов.

Избегайте использования избыточных полных ссылок

На такие сущности, как таблицы и материализованные представления, ссылаются по имени. Например, на таблицу T можно ссылаться просто T ( неквалифицированное имя) или с помощью квалификатора базы данных (например database("DB").T , если таблица находится в базе данных с именем DB) или с помощью полного имени (например, cluster("X.Y.kusto.windows.net").database("DB").T).

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

  1. Неквалифицированные имена проще определить (для читателя-человека) как принадлежащие базе данных в область.

  2. Ссылки на сущности базы данных в область всегда выполняются по крайней мере так же быстро, а в некоторых случаях и гораздо быстрее, а затем сущности, принадлежащие другим базам данных (особенно если эти базы данных находятся в другом кластере). Избегание полных имен помогает читателю делать правильные действия.

Примечание

Это не значит, что полные имена плохо скажутся на производительности. На самом деле, Kusto в большинстве случаев может определить, когда полное имя ссылается на сущность, принадлежающую базе данных в область, и "короткое замыкание" запроса, чтобы он не рассматривался как межкластный запрос. Однако мы рекомендуем не полагаться на это, если это не требуется, по указанным выше причинам.