大数据数据库后端【免费下载链接】prestoThe official home of the Presto distributed SQL query engine for big data项目地址https://gitcode.com/gh_mirrors/pre/presto点击查看免费下载EXPLAIN ANALYZE 是 Presto 中唯一能够真正执行语句并返回分布式执行计划 每个操作真实开销的诊断命令。本指南以 Presto 官方文档为基础结合仓库源码SQL 文法定义、语句分析器、执行计划打印器、ExplainAnalyzeOperator 与测试用例深入讲解其语法、输出解读、VERBOSE 模式与 JSON 格式帮助你用它定位数据倾斜、哈希碰撞异常与热点算子。语法SynopsisEXPLAIN ANALYZE [VERBOSE] [(format TEXT|JSON)] statement各组成部分说明如下语法元素含义EXPLAIN ANALYZE执行语句并展示分布式执行计划及各操作的开销VERBOSE可选。输出更详细的信息与底层统计量理解这些信息通常需要了解 Presto 内部实现细节(format TEXT\|JSON)可选。指定输出格式默认是TEXT可选JSONstatement要执行并分析的目标语句如 SELECT从语法层面看EXPLAIN ANALYZE? VERBOSE? (( explainOption ... ))? statement这条产生式定义在 SqlBase.g4 中。注意VERBOSE既可以跟在ANALYZE之后也可以独立出现而format选项与TYPE如DISTRIBUTED等通用 explain 选项一样被解析进括号列表。与普通 EXPLAIN 的区别EXPLAIN只展示查询的分布式执行计划包含估算成本不执行语句。EXPLAIN ANALYZE先真正执行语句再基于真实运行统计信息输出分布式执行计划与每个计划节点的实际开销CPU、Scheduled、Input、Output 等。EXPLAIN ANALYZE VERBOSE在分析模式基础上额外输出底层统计量如窗口算子的驱动数、索引大小、分区大小等。语义校验的源码约束在语义分析阶段StatementAnalyzer.java 的visitExplain对 EXPLAIN ANALYZE 做了以下硬性校验只支持单个format选项only a single format option is supported in EXPLAIN ANALYZEformat 只允许TEXT或JSONonly TEXT and JSON formats are supported in EXPLAIN ANALYZETYPE 只允许DISTRIBUTEDonly DISTRIBUTED type is supported in EXPLAIN ANALYZE。也就是说EXPLAIN ANALYZE (TYPE LOGICAL)这类写法是不被接受的。描述DescriptionEXPLAIN ANALYZE执行该语句并展示语句的分布式执行计划以及每个操作的开销cost。VERBOSE选项会给出更详细的信息和低层统计量理解这些内容可能需要了解 Presto 内部机制与实现细节。输出格式可通过format选项设置默认输出格式为TEXT。注意统计信息可能并非完全精确尤其是执行很快的查询例如涉及小表、内存表或刚执行完的缓存查询其数值波动和采样误差会更明显。底层执行原理从实现上看EXPLAIN ANALYZE并不是在协调器上事后画图而是把计划本身当作一个真实的查询来调度执行分析器analyzer把ExplainAnalyze语句改写为带 ExplainAnalyzeNode 的查询计划查询执行期间ExplainAnalyzeOperator 负责吸收上游所有真实运行的数据页addInput中直接忽略输入内容并持续等待最终 Stage 统计信息就绪当所有子 Stage 都进入 final 状态后见hasFinalStageInfo/isFinalStageInfo其中对尚未完成的 stage 会以 100ms 间隔轮询等待该算子通过QueryPerformanceFetcher拉取 QueryInfo 中的完整StageInfo根据 format 分派到 PlanPrinterTEXT→textDistributedPlan(...)并把verbose标志透传给TextRendererJSON→jsonDistributedPlan(...)最终把渲染出的计划文本作为单行 VARCHAR 输出返回给客户端。测试方面AbstractTestQueries.java 的testExplainOfExplainAnalyze验证了EXPLAIN (EXPLAIN ANALYZE SELECT * FROM orders)这类对 EXPLAIN ANALYZE 再做 EXPLAIN的嵌套场景能够正常产出逻辑计划说明 EXPLAIN ANALYZE 可以像普通查询一样被继续包装分析。示例TEXT 格式解读TPC-H 查询以下示例来自官方文档在presto:tiny提示符下执行它对 TPC-H tiny 规模的 5 表连接查询做真实执行与统计输出presto:tiny EXPLAIN ANALYZE SELECT - s.acctbal, - s.name, - n.name, - p.partkey, - p.mfgr, - s.address, - s.phone, - s.comment - FROM - part p, - supplier s, - partsupp ps, - nation n, - region r - WHERE - p.partkey ps.partkey - AND s.suppkey ps.suppkey - AND p.size 15 - AND p.type like %BRASS - AND s.nationkey n.nationkey - AND n.regionkey r.regionkey - AND r.name EUROPE - AND ps.supplycost ( - SELECT - min(ps.supplycost) - FROM - partsupp ps, - supplier s, - nation n, - region r - WHERE - p.partkey ps.partkey - AND s.suppkey ps.suppkey - AND s.nationkey n.nationkey - AND n.regionkey r.regionkey - AND r.name EUROPE - ) - ORDER BY - s.acctbal desc, - n.name, - s.name, - p.partkey - LIMIT 100;对应的分布式执行计划输出节选Query Plan ----------------------------------------------------------------------------------------------- ... Fragment 4 [SOURCE] CPU: 31.55ms, Scheduled: 38.34ms, Input: 8,020 rows (260B); per task: avg.: 8,020.00 std.dev.: 0.00, Output: 1,196 rows (21.02kB), 1 tasks Output layout: [partkey_15, min_73] Output partitioning: HASH [partkey_15] Output encoding: COLUMNAR Stage Execution Strategy: UNGROUPED_EXECUTION - Aggregate(PARTIAL)[partkey_15][PlanNodeId 3023] [partkey_15:bigint, min_73:double] CPU: 3.00ms (1.74%), Scheduled: 4.00ms (0.54%), Output: 1,196 rows (21.02kB) Input total: 1,600 rows (40.63kB), avg.: 400.00 rows, std.dev.: 0.00% Collisions avg.: 4.50 (160.41% est.), Collisions std.dev.: 86.78% min_73 : presto.default.min((supplycost_18)) (1:365) - InnerJoin[PlanNodeId 2455][(suppkey_16 suppkey_21)] [partkey_15:bigint, supplycost_18:double] Estimates: {source: CostBasedSourceInfo, rows: 1,600 (28.13kB), cpu: 684,460.00, memory: 225.00, network: 234.00} CPU: 11.00ms (6.40%), Scheduled: 13.00ms (1.77%), Output: 1,600 rows (40.63kB) Left (probe) Input total: 8,000 rows (210.94kB), avg.: 2,000.00 rows, std.dev.: 0.00% Right (build) Input total: 20 rows (260B), avg.: 1.25 rows, std.dev.: 60.00% Collisions avg.: 0.40 (30.84% est.), Collisions std.dev.: 183.71% Distribution: REPLICATED - ScanFilter[PlanNodeId 9,2699][table TableHandle {connectorIdtpch, connectorHandlepartsupp:sf0.01, layoutOptional[partsupp:sf0.01]}, grouped false, filterPredicate (not(IS_NULL(partkey_15))) AND (not(IS_NULL(suppkey_16)))] [partkey_15:bigint, suppkey_16:bigint, supplycost_18:double] Estimates: {source: CostBasedSourceInfo, rows: 8,000 (210.94kB), cpu: 216,000.00, memory: 0.00, network: 0.00}/{source: CostBasedSourceInfo, rows: 8,000 (210.94kB), cpu: 432,000.00, memory: 0.00, network: 0.00} CPU: 14.00ms (8.14%), Scheduled: 16.00ms (2.17%), Output: 8,000 rows (210.94kB) Input total: 8,000 rows (0B), avg.: 2,000.00 rows, std.dev.: 0.00% partkey_15 : tpch:partkey (1:389) supplycost_18 : tpch:supplycost (1:389) suppkey_16 : tpch:suppkey (1:389) Input: 8,000 rows (0B), Filtered: 0.00% - LocalExchange[PlanNodeId 2949][HASH] (suppkey_21) [suppkey_21:bigint] Estimates: {source: CostBasedSourceInfo, rows: 20 (180B), cpu: 7,480.00, memory: 54.00, network: 234.00} CPU: 0.00ns (0.00%), Scheduled: 0.00ns (0.00%), Output: 20 rows (260B) Input total: 20 rows (260B), avg.: 1.25 rows, std.dev.: 225.39% - RemoteSource[5] [suppkey_21:bigint] CPU: 0.00ns (0.00%), Scheduled: 0.00ns (0.00%), Output: 20 rows (260B) Input total: 20 rows (260B), avg.: 1.25 rows, std.dev.: 225.39% ...输出结构阅读方法Fragment执行片段每个 Fragment 是一个可在节点上并行执行的计划子树。Fragment 4 [SOURCE]表示该片段直接读取数据源source。片段级统计行展示了整个片段的 CPU 总耗时31.55ms、调度耗时38.34ms、输入行数/字节、每任务平均值与标准差、输出行数与任务数。Stage Execution Strategy如UNGROUPED_EXECUTION表示该阶段未按 group 分组执行与GROUPED_EXECUTION相对后者常见于聚合类查询。计划节点Plan Node如Aggregate(PARTIAL)、InnerJoin、ScanFilter、LocalExchange、RemoteSource。每个节点带PlanNodeId其统计信息包括CPU/Scheduled节点消耗的 CPU 时间与调度墙钟时间括号内为该节点占整片段的百分比Output该节点实际输出的行数与字节数Input total/avg./std.dev.输入总行数、每个 task 实例的平均输入行数与标准差标准差百分比越大说明各节点实例间输入越不均衡即潜在的数据倾斜Collisions avg./Collisions std.dev.哈希表碰撞的平均次数与标准差括号内是相对估算值的百分比——这是判断哈希碰撞异常的关键指标Estimates基于成本的估算行数、CPU、内存与网络开销来自CostBasedSourceInfo。输出表达式与赋值来源如min_73 : presto.default.min((supplycost_18)) (1:365)其中(1:365)表示该表达式在 SQL 文本中的位置行:列partkey_15 : tpch:partkey表示输出列由 tpch 连接器的partkey列赋值而来。Join 细节InnerJoin节点会列出Left (probe)与Right (build)两路输入各自的统计以及Distribution: REPLICATED右表被复制广播到所有 worker。官方文档特别提醒各计划节点的相对成本基于墙钟时间wall time计算它不一定与 CPU 时间相关。例如一个节点 CPU 占比 1.74% 但 Scheduled 占比可能不同这是因为调度时间包含等待、网络传输与线程调度开销。因此应结合 CPU 与 Scheduled 两列综合判断热点。对于每个计划节点还可以看到附加统计例如每个节点实例的平均输入量、相关计划节点的平均哈希碰撞次数。这些统计在检测查询的数据异常倾斜 skewness、异常哈希碰撞时非常有用。VERBOSE 模式窗口算子等底层统计当使用VERBOSE选项时部分算子会报告额外信息。例如窗口函数算子会输出以下内容EXPLAIN ANALYZE VERBOSE SELECT count(clerk) OVER() FROM orders WHERE orderdate date 1995-01-01; Query Plan ----------------------------------------------------------------------------------------------- ... - Window[] [clerk:varchar(15), count:bigint] Cost: {rows: ?, bytes: ?} CPU fraction: 75.93%, Output: 8130 rows (230.24kB) Input avg.: 8130.00 lines, Input std.dev.: 0.00% Active Drivers: [ 1 / 1 ] Index size: std.dev.: 0.00 bytes , 0.00 rows Index count per driver: std.dev.: 0.00 Rows per driver: std.dev.: 0.00 Size of partition: std.dev.: 0.00 count : count(clerk) ...VERBOSE 模式下窗口算子新增的统计量含义统计项含义CPU fraction窗口计算消耗的 CPU 时间占节点总时间的比例此处 75.93%说明窗口排序/计算是该节点主要开销Active Drivers实际激活的驱动driver数/总驱动数[ 1 / 1 ]表示单并发执行Index size窗口内部索引用于定位分区内行的大小以字节与行数衡量Index count per driver每个驱动维护的索引数量Rows per driver每个驱动处理的行数Size of partition每个窗口分区的行数大小注意Cost: {rows: ?, bytes: ?}显示为?说明该窗口节点的成本估算缺失——这正体现了 EXPLAIN ANALYZE 中估算成本与真实统计两套信息的差异真实统计来自执行过程估算成本来自优化器模型。VERBOSE的底层透传逻辑可参见 ExplainAnalyzeOperator.java 中textDistributedPlan(..., verbose)的调用以及 PlanPrinter.java 将verbose标志传入TextRenderer的实现路径。JSON 格式输出通过(format JSON)可以要求输出结构化 JSON便于程序化解析与后续可视化EXPLAIN ANALYZE (format JSON) SELECT count(*) FROM orders;JSON 输出由 PlanPrinter.jsonDistributedPlan 生成与 TEXT 格式共享同一份 StageInfo 运行时统计来源但以树形 JSON 组织包含fragments、plan节点、estimates、stats等字段。注意 JSON 模式目前不接收 VERBOSE 的额外低层统计参考 ExplainAnalyzeOperator 的分支实现。统计准确性说明官方文档明确提示统计信息可能不完全准确尤其是快速完成的查询。原因可以从执行机制推断快速查询的总执行时间极短毫秒级各算子的计时粒度与采样窗口有限误差占比被放大部分统计如哈希碰撞估算、CPU 占比基于采样或估算模型与真实值存在偏差输出中Estimates一行来自 CBO 的成本估算与真实CPU/Input统计属于不同来源二者不应直接对比。因此在对查询做性能诊断时建议对同一查询多次执行EXPLAIN ANALYZE观察数值稳定性并结合std.dev.标准差判断是否存在节点间不均衡。实战排查指引结合文档示例与源码结构EXPLAIN ANALYZE可用于以下典型诊断场景数据倾斜检测观察各算子Input total ... avg.: x rows, std.dev.: y%中的标准差。标准差显著偏大例如超过 100%说明不同 task 实例处理行数差异悬殊可考虑在 JOIN 或 GROUP BY 键上做加盐salting或调整分区策略。哈希碰撞异常Collisions avg.与Collisions std.dev.反映哈希表的碰撞情况括号内为相对估算值的百分比。异常高的碰撞如示例中 Aggregate 的160.41% est.可能源于 hash 分布不佳可检查是否有低基数字段被用作分布键。定位耗时热点算子比较各节点的CPU百分比与Scheduled百分比。CPU 占比高说明计算密集Scheduled 占比高而 CPU 低说明存在等待网络、I/O 或调度瓶颈。验证连接器行为ScanFilter节点中的TableHandle {connectorIdtpch, ...}与Input: 8,000 rows (0B), Filtered: 0.00%展示了连接器下推与过滤效果可用于确认谓词下推是否生效。参见See AlsoEXPLAIN 语法仅展示分布式执行计划含估算成本不执行语句SQL 文法定义SqlBase.g4语义分析StatementAnalyzer.java运行时统计输出实现ExplainAnalyzeOperator.java、PlanPrinter.java相关测试AbstractTestQueries.javatestExplainOfExplainAnalyze。赞分享大数据数据库后端【免费下载链接】prestoThe official home of the Presto distributed SQL query engine for big data项目地址https://gitcode.com/gh_mirrors/pre/presto点击查看免费下载相关推荐Presto EXPLAIN 语句完全指南逻辑计划、分布式计划与执行计划诊断实战Presto EXPLAIN 语句完全指南逻辑计划、分布式计划与执行计划诊断实战 本文以 Presto 官方文档 explain.rst https://li大数据数据库后端TDengine 查询执行计划分析实战使用 EXPLAIN 与 EXPLAIN ANALYZE 定位慢查询瓶颈TDengine 查询执行计划分析实战使用 EXPLAIN 与 EXPLAIN ANALYZE 定位慢查询瓶颈 TDengine 的 EXPLAIN / EX数据库时序数据库物联网大数据实时分析云原生TDengine EXPLAIN 与 EXPLAIN ANALYZE 执行计划详解从算子阅读到慢查询诊断TDengine EXPLAIN 与 EXPLAIN ANALYZE 执行计划详解从算子阅读到慢查询诊断 本文以 TDengine 的 EXPLAIN / E数据库时序数据库大数据物联网云原生上一篇Rerun ROS2桥接工具使用指南机器人传感器数据实时可视化下一篇GitHub_Trending/rea/reader最新更新2024功能盘点创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
