性能分析对于理解特定查询为何表现出特定性能特征至关重要。DuckDB 包含几项内置功能,可实现查询性能分析,本页将介绍这些功能。有关使用 EXPLAIN
的高层示例,请参阅“检查查询计划”页面。有关深入的解释,请参阅开发者文档中的“性能分析”页面。
语句
EXPLAIN
语句
性能分析查询的第一步可以包括检查查询计划。EXPLAIN
语句显示查询计划并描述其幕后的运行情况。
EXPLAIN ANALYZE
语句
查询计划有助于开发者理解查询的性能特征。然而,通常还需要检查各个运算符的性能数据以及流经它们的数据基数。EXPLAIN ANALYZE
语句能够获取这些信息,因为它会漂亮地打印查询计划并执行查询。因此,它提供了实际的运行时性能数据。
FORMAT
选项
EXPLAIN [ANALYZE]
语句允许导出为多种格式
text
– 默认的 ASCII 艺术风格输出graphviz
– 生成 DOT 输出,可使用 Graphviz 渲染html
– 生成 HTML 输出,可使用 treeflex 渲染json
– 生成 JSON 输出
要指定格式,请使用 FORMAT
标签
EXPLAIN (FORMAT html) SELECT 42 AS x;
Pragmas
DuckDB 支持多种编译指示(pragmas),用于打开和关闭性能分析,并控制性能分析输出的详细程度。
以下编译指示可用,并可以通过 PRAGMA
或 SET
进行设置。它们也可以通过 RESET
后跟设置名称进行重置。更多信息,请参阅编译指示页面中的“性能分析”部分。
设置 | 描述 | 默认值 | 选项 |
---|---|---|---|
enable_profiling , enable_profile |
开启性能分析 | query_tree |
query_tree , json , query_tree_optimizer , no_output |
profiling_output |
设置性能分析输出文件 | 控制台 | 文件路径 |
profiling_mode |
切换额外的优化器和规划器指标 | 标准 |
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 |
绝对值 | ✅ | 查询返回的行数 | |
SYSTEM_PEAK_BUFFER_MEMORY |
uint64 |
字节 | ✅ | 查询期间系统所有已分配缓冲区的峰值内存使用量 | |
SYSTEM_PEAK_TEMP_DIR_SIZE |
uint64 |
字节 | ✅ | 查询期间系统临时目录的峰值大小 |
累积指标
DuckDB 还支持多种累积指标,这些指标在所有节点中均可用。在 QUERY_ROOT
节点中,这些指标表示查询中所有运算符相应指标的总和。OPERATOR
节点表示该运算符特定指标及其所有子节点(递归地)指标的总和。
这些累积指标可以独立启用,即使底层特定指标被禁用。下表显示了累积指标。它还描绘了 DuckDB 用来计算累积指标的依据指标。
度量 | 单位 | 累积计算的指标 |
---|---|---|
CPU_TIME |
秒 | OPERATOR_TIMING |
CUMULATIVE_CARDINALITY |
绝对值 | OPERATOR_CARDINALITY |
CUMULATIVE_ROWS_SCANNED |
绝对值 | OPERATOR_ROWS_SCANNED |
CPU_TIME
衡量累积的运算符时间。它不包括在其他阶段(如解析、查询规划等)花费的时间。因此,对于某些查询,QUERY_ROOT
中的 LATENCY
可能大于 CPU_TIME
。
详细性能分析
当 profiling_mode
设置为 detailed
时,会启用一组额外的指标,这些指标仅在 QUERY_ROOT
节点中可用。这包括 OPTIMIZER
、PLANNER
和 PHYSICAL_PLANNER
指标。它们以秒为单位测量,并以 double
类型返回。可以单独切换这些额外的指标。
优化器指标
在 QUERY_ROOT
节点,有衡量每个优化器所花费时间的指标。这些指标仅在该特定优化器启用时才可用。可用优化可以通过duckdb_optimizers()
表函数进行查询。
每个优化器都有一个相应的指标,遵循模板:OPTIMIZER_OPTIMIZER_NAME
。例如,OPTIMIZER_JOIN_ORDER
指标对应于 JOIN_ORDER
优化器。
此外,以下指标可用于支持优化器指标
ALL_OPTIMIZERS
:启用所有优化器指标并测量优化器父节点所花费的时间。CUMULATIVE_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 脚本可以将其渲染为查询图。该脚本需要安装 duckdb
Python 模块。它会生成一个 HTML 文件并在您的网络浏览器中打开。
python -m duckdb.query_graph /path/to/file.json
查询计划中的表示法
在查询计划中,哈希连接运算符遵循以下约定:连接的探查侧是左操作数,而构建侧是右操作数。
查询计划中的连接运算符显示使用的连接类型
- 内连接表示为
INNER
。 - 左外连接和右外连接分别表示为
LEFT
和RIGHT
。 - 全外连接表示为
FULL
。
提示 要可视化查询计划,请考虑使用由蒂宾根大学数据库系统研究组开发的 DuckDB 执行计划可视化工具。