Spec-Zone.ru › DuckDB

Профилирование

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

EXPLAIN Запрос

Первым шагом при профилировании запроса может быть изучение плана запроса. Запрос EXPLAIN отображает план запроса и описывает то, что происходит под капотом.

EXPLAIN ANALYZE Запрос

План запроса помогает разработчикам понять характеристики производительности запроса. Однако часто также необходимо изучить числовые показатели производительности отдельных операторов и кардинальности, которые через них проходят. Запрос EXPLAIN ANALYZE позволяет получить эти данные, так как он красиво отображает план запроса и также выполняет запрос. Таким образом, он предоставляет фактические временные показатели производительности.

Прагмы

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

Доступны следующие прагмы, которые можно задать, используя либо PRAGMA или SET. Их также можно сбросить, используя RESET, за которым следует имя настройки. Более подробную информацию можно найти в разделе «Профилирование» на странице прагм “Profiling”.

Настройка Описание Значение по умолчанию Варианты
enable_profiling, enable_profile Включить профилирование. query_tree query_tree, json, query_tree_optimizer, no_output
profiling_output Установить файл вывода профилирования. Консоль Путь к файлу.
profiling_mode Включить дополнительные метрики оптимизатора и планировщика. standard standard, detailed
custom_profiling_settings Включить или отключить определенные метрики. Все метрики, кроме тех, что активированы подробным профилированием. Объект JSON, соответствующий следующему: {"METRIC_NAME": "boolean", ...}. Смотрите раздел метрики ниже.
disable_profiling, disable_profile Отключить профилирование.

Метрики

Дерево запроса имеет два типа узлов: узлы QUERY_ROOT и OPERATOR. Узел QUERY_ROOT относится исключительно к узлу верхнего уровня, и метрики, которые он содержит, измеряются по всему запросу. Узлы OPERATOR относятся к отдельным операторам в плане запроса. Некоторые метрики доступны только для узлов QUERY_ROOT, в то время как другие — только для узлов OPERATOR. Ниже представлена таблица, описывающая каждую метрику и для каких узлов она доступна.

Помимо QUERY_NAME и OPERATOR_TYPE, можно включить или отключить все метрики.

Метрика Тип возвращаемого значения Единица измерения Запрос Оператор Описание
BLOCKED_THREAD_TIME double секунды ✅ Общее время блокировки потоков.
EXTRA_INFO string ✅ ✅ Уникальные метрики операторов.
LATENCY double секунды ✅ Общее время выполнения запроса.
OPERATOR_CARDINALITY uint64 абсолютное значение ✅ Кардинальность каждого оператора, т. е. количество строк, возвращаемых ему родительским узлом. Операторный эквивалент ROWS_RETURNED..
OPERATOR_ROWS_SCANNED uint64 абсолютное значение ✅ Общее количество просканированных строк каждым оператором.
OPERATOR_TIMING double секунды ✅ Время, затраченное каждым оператором. Операторный эквивалент LATENCY..
OPERATOR_TYPE string ✅ Имя каждого оператора.
QUERY_NAME string ✅ Строка запроса.
RESULT_SET_SIZE uint64 байты ✅ ✅ Размер результата.
ROWS_RETURNED uint64 абсолютное значение ✅ Количество строк, возвращенных запросом.

Кумулятивные метрики

DuckDB также поддерживает несколько кумулятивных метрик, которые доступны во всех узлах. В узле QUERY_ROOT эти метрики представляют собой сумму соответствующих метрик по всем операторам в запросе. Узлы OPERATOR представляют собой сумму метрики конкретного оператора и всех его потомков рекурсивно.

Эти кумулятивные метрики могут быть включены независимо, даже если соответствующие метрики отключены. В таблице ниже показаны кумулятивные метрики. Также показана метрика, на основе которой DuckDB вычисляет кумулятивную метрику.

Метрика Единица измерения Метрика, вычисляемая кумулятивно
CPU_TIME секунды OPERATOR_TIMING
CUMULATIVE_CARDINALITY абсолютное значение OPERATOR_CARDINALITY
CUMULATIVE_ROWS_SCANNED абсолютное значение OPERATOR_ROWS_SCANNED

CPU_TIME измеряет кумулятивные временные затраты операторов. В нее не входит время, затраченное на другие стадии, такие как парсинг, планирование запроса и т. д. Поэтому для некоторых запросов LATENCY в узле QUERY_ROOT может быть больше, чем CPU_TIME.

Детальное профилирование

Когда profiling_mode установлено в detailed, включается дополнительный набор метрик, которые доступны только в узле QUERY_ROOT Это включает OPTIMIZER, PLANNER и PHYSICAL_PLANNER метрики. Они измеряются в секундах и возвращаются как double. Можно включать и отключать каждую из этих дополнительных метрик индивидуально.

Метрики оптимизатора

В узле QUERY_ROOT есть метрики, которые измеряют время, затраченное каждым оптимизатором. Эти метрики доступны только при включенном соответствующем оптимизаторе. Доступные оптимизации можно запросить, используя duckdb_optimizers() table function.

Каждый оптимизатор имеет соответствующую метрику, которая следует шаблону: OPTIMIZER_⟨OPTIMIZER_NAME⟩. Например, метрика OPTIMIZER_JOIN_ORDER соответствует оптимизатору JOIN_ORDER.

Кроме того, доступны следующие метрики для поддержки метрик оптимизатора:

  • ALL_OPTIMIZERS: Включает все метрики оптимизатора и измеряет время, которое родительский узел оптимизатора тратит на свою работу.
  • CUMMULATIVE_OPTIMIZER_TIMING: Кумулятивная сумма всех метрик оптимизатора. Она может использоваться без включения всех метрик оптимизатора.

Метрики планировщика

Планировщик отвечает за генерацию логического плана. В настоящее время DuckDB измеряет две метрики в планировщике:

  • PLANNER: Время генерации логического плана из обработанных узлов SQL.
  • PLANNER_BINDING: Время привязки логического плана.

Метрики физического планировщика

Физический планировщик отвечает за генерацию физического плана из логического плана. Ниже приведены метрики, поддерживаемые физическим планировщиком:

  • PHYSICAL_PLANNER: Время, потраченное на генерацию физического плана.
  • PHYSICAL_PLANNER_COLUMN_BINDING: Время, потраченное на привязку столбцов в логическом плане к физическим столбцам.
  • PHYSICAL_PLANNER_RESOLVE_TYPES: Время, потраченное на преобразование типов в логическом плане к физическим типам.
  • PHYSICAL_PLANNER_CREATE_PLAN: Время, потраченное на создание физического плана.

Примеры пользовательских метрик

Следующие примеры демонстрируют, как включить пользовательское профилирование и установить формат вывода в json. В первом примере мы включаем профилирование и устанавливаем вывод в файл. Мы включаем только EXTRA_INFO, OPERATOR_CARDINALITY, и OPERATOR_TIMING.

CREATE TABLE students (name VARCHAR, sid INTEGER);
CREATE TABLE exams (eid INTEGER, subject VARCHAR, sid INTEGER);
INSERT INTO students VALUES ('Mark', 1), ('Joe', 2), ('Matthew', 3);
INSERT INTO exams VALUES (10, 'Physics', 1), (20, 'Chemistry', 2), (30, 'Literature', 3);

PRAGMA enable_profiling = 'json';
PRAGMA profiling_output = '/path/to/file.json';

PRAGMA custom_profiling_settings = '{"CPU_TIME": "false", "EXTRA_INFO": "true", "OPERATOR_CARDINALITY": "true", "OPERATOR_TIMING": "true"}';

SELECT name
FROM students
JOIN exams USING (sid)
WHERE name LIKE 'Ma%';

Содержимое файла после выполнения запроса:

{
    "extra_info": {},
    "query_name": "SELECT name\nFROM students\nJOIN exams USING (sid)\nWHERE name LIKE 'Ma%';",
    "children": [
        {
            "operator_timing": 0.000001,
            "operator_cardinality": 2,
            "operator_type": "PROJECTION",
            "extra_info": {
                "Projections": "name",
                "Estimated Cardinality": "1"
            },
            "children": [
                {
                    "extra_info": {
                        "Join Type": "INNER",
                        "Conditions": "sid = sid",
                        "Build Min": "1",
                        "Build Max": "3",
                        "Estimated Cardinality": "1"
                    },
                    "operator_cardinality": 2,
                    "operator_type": "HASH_JOIN",
                    "operator_timing": 0.00023899999999999998,
                    "children": [
...

Второй пример добавляет подробные метрики в вывод.

PRAGMA profiling_mode = 'detailed';

SELECT name
FROM students
JOIN exams USING (sid)
WHERE name LIKE 'Ma%';

Содержимое выведенного файла:

{
  "all_optimizers": 0.001413,
  "cumulative_optimizer_timing": 0.0014120000000000003,
  "planner": 0.000873,
  "planner_binding": 0.000869,
  "physical_planner": 0.000236,
  "physical_planner_column_binding": 0.000005,
  "physical_planner_resolve_types": 0.000001,
  "physical_planner_create_plan": 0.000226,
  "optimizer_expression_rewriter": 0.000029,
  "optimizer_filter_pullup": 0.000002,
  "optimizer_filter_pushdown": 0.000102,
...
  "optimizer_column_lifetime": 0.000009999999999999999,
  "rows_returned": 2,
  "latency": 0.003708,
  "cumulative_rows_scanned": 6,
  "cumulative_cardinality": 11,
  "extra_info": {},
  "cpu_time": 0.000095,
  "optimizer_build_side_probe_side": 0.000017,
  "result_set_size": 32,
  "blocked_thread_time": 0.0,
  "query_name": "SELECT name\nFROM students\nJOIN exams USING (sid)\nWHERE name LIKE 'Ma%';",
  "children": [
    {
      "operator_timing": 0.000001,
      "operator_rows_scanned": 0,
      "cumulative_rows_scanned": 6,
      "operator_cardinality": 2,
      "operator_type": "PROJECTION",
      "cumulative_cardinality": 11,
      "extra_info": {
        "Projections": "name",
        "Estimated Cardinality": "1"
      },
      "result_set_size": 32,
      "cpu_time": 0.000095,
      "children": [
...

Графики запросов

Также можно отобразить выходные данные профилирования в виде графа запроса. Граф запроса визуально представляет план запроса, показывая операторы и их взаимосвязи. План запроса должен быть выведен в формате json и сохранён в файле. После записи выходных данных профилирования в назначенный файл, скрипт Python может отобразить их в виде графа запроса. Для работы скрипта необходимо установить модуль Python duckdb. Он генерирует HTML-файл и открывает его в вашем веб-браузере.

python -m duckdb.query_graph /path/to/file.json

Нотация в планах запросов

В планах запросов операторы hash join следуют следующей конвенции: сторона пробы соединения — это левый операнд, а сторона построения — это правый операнд.

Операторы соединения в плане запроса показывают тип соединения, используемого:

  • Внутренние соединения обозначаются как INNER.
  • Левые внешние соединения и правые внешние соединения обозначаются как LEFT и RIGHT соответственно.
  • Полные внешние соединения обозначаются как FULL.

© Copyright 2018–2024 Stichting DuckDB Foundation
Licensed under the MIT License.
https://duckdb.org/docs/dev/profiling.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API