Поделиться через


Использование ресурсов запроса

Применимо: ✅Microsoft FabricAzure Data Explorer

В этом документе описаны сведения о потреблении ресурсов, возвращаемые в ответе на запрос Kusto.

При выполнении запроса служба возвращает не только результаты запроса, но и подробные сведения о ресурсах, потребляемых во время выполнения запроса.

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

Данные потребления ресурсов возвращаются в объекте в QueryResourceConsumption составе ответа запроса, как правило, в формате JSON. Объект можно найти в средствах мониторинга или программном доступе.

Структура объекта QueryResourceConsumption

Объект QueryResourceConsumption обычно включает следующие основные разделы:

  • QueryHash: уникальный идентификатор структуры запроса. Этот хэш представляет запрос без его литеральных значений, что позволяет идентифицировать аналогичные шаблоны запросов, даже если определенные литеральные значения отличаются. Например, запросы, такие Events | where Timestamp > datetime(2023-01-01) как и Events | where Timestamp > datetime(2023-02-01) будут иметь одинаковый запросHash, так как они используют одну и ту же структуру, только отличаясь в значениях даты и времени литерала.
  • ExecutionTime: общее время выполнения в секундах
  • resource_usage: подробный разбивка используемых ресурсов
  • input_dataset_statistics: статистика об обработанных входных данных
  • dataset_statistics: статистика о результирующем наборе данных
  • cross_cluster_resource_usage: сведения о ресурсах, используемых в кластерах, где это необходимо

Сведения об использовании ресурсов

В разделе об использовании ресурсов содержатся подробные сведения о ресурсах, потребляемых во время выполнения запроса. Раздел включает следующие подразделы.

Использование кэша

В resource_usage.cache.shards разделе содержатся сведения о том, как запрос использовал кэш:

Объект Недвижимость Описание
hot Данные, обслуживаемые из горячего кэша
hitbytes Объем данных, успешно полученных из горячего кэша в байтах
missbytes Объем данных, не найденных в горячем кэше в байтах
retrievebytes Объем данных, полученных из хранилища для удовлетворения пропущенных в байтах
cold Данные, обслуживаемые из холодного кэша
hitbytes Объем данных, успешно полученных из холодного кэша в байтах
missbytes Объем данных в байтах не найден в холодном кэше в байтах
retrievebytes Объем данных, полученных из хранилища для удовлетворения пропущенных в байтах
bypassbytes Объем данных, которые обошли кэш в байтах
results_cache_origin Сведения о исходном запросе, результаты которого были кэшированы и повторно использованы
client_request_id Уникальный идентификатор исходного запроса, заполняющего кэш
started_on Метка времени при выполнении исходного запроса, заполненного кэшем
partial_query_results Статистика кэширования на уровне сегментов, если включена
hits Количество результатов запроса уровня сегментов, найденных в кэше
misses Количество результатов запроса уровня сегментов, отсутствующих в кэше

Использование ЦП

В resource_usage.cpu разделе содержатся сведения о потреблении ЦП:

Объект Недвижимость Описание
user Время ЦП в пользовательском режиме
kernel Время ЦП в режиме ядра
total cpu Общее время, затраченное на ЦП
breakdown Дальнейшая разбивка использования ЦП
query execution Время ЦП для выполнения запроса
query planning Время ЦП для планирования запросов

Использование памяти

В resource_usage.memory этом разделе содержатся сведения о потреблении памяти:

Объект Недвижимость Описание
peak_per_node Пиковое использование памяти на узел в байтах

Использование сети

В resource_usage.network этом разделе содержатся сведения об использовании сети:

Объект Недвижимость Описание
inter_cluster_total_bytes Всего байтов, передаваемых в кластере
cross_cluster_total_bytes Общее количество байтов, передаваемых между кластерами

Статистика входного набора данных

В input_dataset_statistics этом разделе содержатся сведения об обработанных исходных данных:

Объект Недвижимость Описание
extents Сведения о экстентах данных
total Общее количество экстентов во всех таблицах, на которые ссылается запрос
scanned Количество отсканированных экстентов (проверяется узлами запросов)
scanned_min_datetime Минимальное время даты и времени сканирования данных
scanned_max_datetime Максимальное время даты и времени сканирования данных
rows Сведения о строках данных
total Общее количество строк во всех таблицах, на которые ссылается запрос
scanned Количество отсканированных строк (проверяется узлами запросов)
rowstores Сведения о данных rowstore
scanned_rows Количество строк, отсканированных из хранилищ строк
scanned_values_size Размер значений, отсканированных из хранилищ строк
shards Сведения о запросах сегментов
total Общее количество сегментов во всех таблицах, на которые ссылается запрос
scanned Количество отсканированных сегментов (проверяется узлами запросов)
external_data Сведения о внешних данных (если применимо)
downloaded_items Количество загруженных элементов из внешних источников данных
downloaded_bytes Количество байтов, скачанных из внешних источников данных
iterated_artifacts Число артефактов, итерированных из внешних источников данных

Интеграция с средствами мониторинга

Данные QueryResourceConsumption можно собирать и анализировать с течением времени для выявления тенденций и аномалий в производительности запросов. Эти данные доступны через:

  • Результаты выполнения запроса
  • .show queries Выходные данные команды
  • Журналы диагностики, экспортированные в решения мониторинга

Мониторинг этих данных может помочь определить возможности оптимизации запросов и отслеживать влияние изменений в моделях данных или шаблонах запросов.

Результаты выполнения запроса

Вы можете получить доступ к необработанным JSON-файлу данных QueryResourceConsumption непосредственно из результатов выполнения запроса. Сведения отображаются в сетке результатов, расположенной под редактором запросов.

  1. Запустите запрос в области запросов.

  2. Перейдите на вкладку статистики результатов запроса.

    Снимок экрана: вкладки результатов запроса с выделенной вкладкой

  3. Просмотрите раздел "Необработанный просмотр JSAN" и выберите полный параметр JSON для прокрутки необработанного JSON.

    Снимок экрана: пример результатов запроса с выделенной областью предварительной версии Raw JSAON.

Программный доступ

В клиентских приложениях вы можете получить доступ к сведениям QueryResourceConsumption программным способом:

// Example of accessing QueryResourceConsumption in C#
var dataSet = kustoClient.ExecuteQuery(query);
var resourceConsumption = GetQueryResourceConsumption(dataSet.Tables[2], false);
Console.WriteLine($"Execution time: {resourceConsumption.ExecutionTime}");
Console.WriteLine($"Memory peak: {resourceConsumption.ResourceUsage.Memory.PeakPerNode}");

Дополнительные сведения см. в статье "Создание приложения для выполнения команд управления".

Примеры

Данные в горячем кэше: в этом примере показан запрос, который был полностью обслуживался из горячего кэша (: 517324, hitbytes: 0) и имел минимальное время выполнения (missbytes0,0045931 секунд). Все данные найдены в горячем кэше, что приводит к очень быстрому выполнению запросов.

{
  "QueryHash": "add172cd28dde0eb",
  "ExecutionTime": 0.0045931,
  "resource_usage": {
    "cache": {
      "shards": {
        "hot": {
          "hitbytes": 517324,
          "missbytes": 0,
          "retrievebytes": 0
        },
        "cold": {
          "hitbytes": 0,
          "missbytes": 0,
          "retrievebytes": 0
        },
        "bypassbytes": 0
      }
    },
    "cpu": {
      "user": "00:00:00",
      "kernel": "00:00:00",
      "total cpu": "00:00:00",
      "breakdown": {
        "query execution": "00:00:00",
        "query planning": "00:00:00"
      }
    },
    "memory": {
      "peak_per_node": 1580848
    },
    "network": {
      "inter_cluster_total_bytes": 27384,
      "cross_cluster_total_bytes": 0
    }
  },
  "input_dataset_statistics": {
    "extents": {
      "total": 1,
      "scanned": 1,
      "scanned_min_datetime": "2016-03-17T08:24:02.6259906Z",
      "scanned_max_datetime": "2016-03-17T08:24:02.6259906Z"
    },
    "rows": {
      "total": 59066,
      "scanned": 59066
    },
    "rowstores": {
      "scanned_rows": 0,
      "scanned_values_size": 0
    },
    "shards": {
      "queries_generic": 1,
      "queries_specialized": 0
    }
  },
  "dataset_statistics": [
    {
      "table_row_count": 10,
      "table_size": 11473
    }
  ],
  "cross_cluster_resource_usage": {}
}

Данные из внешних таблиц: в этом примере показан запрос, обрабатывающий внешние данные. Обратите внимание на большое время выполнения (159,88 секунд) и значительное использование ЦП (более 1 часа общего времени ЦП). В разделе внешних данных показано, что скачано 6709 элементов, в общей сложности около 87,7 ГБ. Это типично для запросов, которые должны получить большие объемы данных из внешних источников, что значительно медленнее, чем запрос данных во внутреннем хранилище Kusto.

{
  "QueryHash": "529656ef4099485b",
  "ExecutionTime": 159.8833962,
  "resource_usage": {
    "cache": {
      "shards": {
        "hot": {
          "hitbytes": 0,
          "missbytes": 0,
          "retrievebytes": 0
        },
        "cold": {
          "hitbytes": 0,
          "missbytes": 0,
          "retrievebytes": 0
        },
        "bypassbytes": 0
      }
    },
    "cpu": {
      "user": "01:01:13.5312500",
      "kernel": "00:00:44.9687500",
      "total cpu": "01:01:58.5000000",
      "breakdown": {
        "query execution": "01:01:58.5000000",
        "query planning": "00:00:00"
      }
    },
    "memory": {
      "peak_per_node": 26834528
    },
    "network": {
      "inter_cluster_total_bytes": 6745,
      "cross_cluster_total_bytes": 0
    }
  },
  "input_dataset_statistics": {
    "extents": {
      "total": 0,
      "scanned": 0,
      "scanned_min_datetime": "0001-01-01T00:00:00.0000000Z",
      "scanned_max_datetime": "0001-01-01T00:00:00.0000000Z"
    },
    "rows": {
      "total": 0,
      "scanned": 0
    },
    "rowstores": {
      "scanned_rows": 0,
      "scanned_values_size": 0
    },
    "shards": {
      "queries_generic": 0,
      "queries_specialized": 0
    },
    "external_data": {
      "downloaded_items": 6709,
      "downloaded_bytes": 87786879356,
      "iterated_artifacts": 6709
    }
  },
  "dataset_statistics": [
    {
      "table_row_count": 2,
      "table_size": 44
    }
  ],
  "cross_cluster_resource_usage": {}
}

Данные из холодного кэша: в этом примере показан запрос, извлекающий данные из холодного кэша (cold.hitbytes127209). Обратите внимание, что из 1250 общих экстентов только 1 было сканировано, и из 50 000 общих строк было сканировано только 40. Это предлагает эффективный запрос, использующий соответствующую фильтрацию. Доступ к холодному кэшу обычно медленнее, чем горячий кэш, но быстрее, чем получение данных непосредственно из хранилища.

{
  "QueryHash": "480873c9b515cea8",
  "ExecutionTime": 1.4233768,
  "resource_usage": {
    "cache": {
      "shards": {
        "hot": {
          "hitbytes": 0,
          "missbytes": 0,
          "retrievebytes": 0
        },
        "cold": {
          "hitbytes": 127209,
          "missbytes": 0,
          "retrievebytes": 0
        },
        "bypassbytes": 0
      }
    },
    "cpu": {
      "user": "00:00:00",
      "kernel": "00:00:00",
      "total cpu": "00:00:00",
      "breakdown": {
        "query execution": "00:00:00",
        "query planning": "00:00:00"
      }
    },
    "memory": {
      "peak_per_node": 2098656
    },
    "network": {
      "inter_cluster_total_bytes": 250676,
      "cross_cluster_total_bytes": 0
    }
  },
  "input_dataset_statistics": {
    "extents": {
      "total": 1250,
      "scanned": 1,
      "scanned_min_datetime": "2024-01-08T07:13:13.6172552Z",
      "scanned_max_datetime": "2024-01-08T07:13:13.6172552Z"
    },
    "rows": {
      "total": 50000,
      "scanned": 40
    },
    "rowstores": {
      "scanned_rows": 0,
      "scanned_values_size": 0
    },
    "shards": {
      "queries_generic": 1,
      "queries_specialized": 0
    }
  },
  "dataset_statistics": [
    {
      "table_row_count": 10,
      "table_size": 123654
    }
  ],
  "cross_cluster_resource_usage": {}
}

Результаты из кэша запросов. В этом примере показано, как выполнить запрос из кэша результатов запроса. Обратите внимание на наличие results_cache_origin раздела, указывающего, что результаты были получены из ранее кэшированного результата запроса. Чрезвычайно быстрое время выполнения (0,0039999 секунд) показывает преимущество кэширования результатов запроса, так как обработка данных не требуется. Кэш содержит сведения о исходном запросе, заполняемом кэшем (client_request_id) и при первоначальном выполнении (started_on). Обратите внимание, что данные не были сканированы из экстентов или строк, как указано нулями в input_dataset_statistics разделе, убедив, что результаты были получены непосредственно из кэша запросов.

{
  "ExecutionTime": 0.0039999,
  "resource_usage": {
    "cache": {
      "shards": {
        "hot": {
          "hitbytes": 0,
          "missbytes": 0,
          "retrievebytes": 0
        },
        "cold": {
          "hitbytes": 0,
          "missbytes": 0,
          "retrievebytes": 0
        },
        "bypassbytes": 0
      },
      "results_cache_origin": {
        "client_request_id": "KE.DF.RunQuery;95b6d241-e684-4a43-91c8-da0d6a854e3e",
        "started_on": "2025-04-22T08:22:24.4719143Z"
      }
    },
    "cpu": {
      "user": "00:00:00.0156250",
      "kernel": "00:00:00",
      "total cpu": "00:00:00.0156250",
      "breakdown": {
        "query execution": "00:00:00.0156250",
        "query planning": "00:00:00"
      }
    },
    "memory": {
      "peak_per_node": 53440160
    },
    "network": {
      "inter_cluster_total_bytes": 13233,
      "cross_cluster_total_bytes": 0
    }
  },
  "input_dataset_statistics": {
    "extents": {
      "total": 0,
      "scanned": 0,
      "scanned_min_datetime": "0001-01-01T00:00:00.0000000Z",
      "scanned_max_datetime": "0001-01-01T00:00:00.0000000Z"
    },
    "rows": {
      "total": 0,
      "scanned": 0
    },
    "rowstores": {
      "scanned_rows": 0,
      "scanned_values_size": 0
    },
    "shards": {
      "queries_generic": 0,
      "queries_specialized": 0
    }
  },
  "dataset_statistics": [
    {
      "table_row_count": 10,
      "table_size": 12121
    }
  ],
  "cross_cluster_resource_usage": {}
}

Результаты из частичного кэша запросов (Per-Shard): в этом примере показан запрос, который используется для кэширования на уровне сегментов, как показано в partial_query_results разделе. В кэше отображается 1 попадание и 0 пропущено, то есть запрос смог получить предварительно вычисляемые результаты для сегмента без необходимости повторной обработки данных. В отличие от примера полного кэша запросов, показано, input_dataset_statistics что данные технически "сканированы" (59 066 строк), но это, скорее всего, просто операция метаданных, так как фактические вычисления были получены из кэша. Обратите внимание на очень быстрое время выполнения (0,0047499 секунд), демонстрируя преимущество производительности частичного кэширования запросов. Кэширование сегментов особенно полезно для запросов, которые многократно обращаются к тем же секциям данных с одинаковыми условиями фильтрации.

{
  "QueryHash": "da3c6dc30e7b203d",
  "ExecutionTime": 0.0047499,
  "resource_usage": {
    "cache": {
      "shards": {
        "hot": {
          "hitbytes": 0,
          "missbytes": 0,
          "retrievebytes": 0
        },
        "cold": {
          "hitbytes": 0,
          "missbytes": 0,
          "retrievebytes": 0
        },
        "bypassbytes": 0
      },
      "partial_query_results": {
        "hits": 1,
        "misses": 0
      }
    },
    "cpu": {
      "user": "00:00:00.0156250",
      "kernel": "00:00:00",
      "total cpu": "00:00:00.0156250",
      "breakdown": {
        "query execution": "00:00:00.0156250",
        "query planning": "00:00:00"
      }
    },
    "memory": {
      "peak_per_node": 1580848
    },
    "network": {
      "inter_cluster_total_bytes": 27428,
      "cross_cluster_total_bytes": 0
    }
  },
  "input_dataset_statistics": {
    "extents": {
      "total": 1,
      "scanned": 1,
      "scanned_min_datetime": "2016-03-17T08:24:02.6259906Z",
      "scanned_max_datetime": "2016-03-17T08:24:02.6259906Z"
    },
    "rows": {
      "total": 59066,
      "scanned": 59066
    },
    "rowstores": {
      "scanned_rows": 0,
      "scanned_values_size": 0
    },
    "shards": {
      "queries_generic": 0,
      "queries_specialized": 0
    }
  },
  "dataset_statistics": [
    {
      "table_row_count": 10,
      "table_size": 11473
    }
  ],
  "cross_cluster_resource_usage": {}
}