7.1 分布式查询规划


7.1 分布式查询规划:一条 SQL 如何拆给全网

分布式查询规划负责把一条全局 SQL,拆成"能在各节点独立执行的局部子查询 + 一台汇总器归并结果",并估算每一步的网络成本。本节走一遍"全局→拆分→本地→汇总"的完整流程,讲清规划器的输出是什么,以及一个糟糕的拆分怎么毁掉性能。

学习目标

阅读完本节,你应当能够:

  1. 说出分布式查询计划的两个层次:全局计划与各节点局部计划。
  2. 描述一个带"聚合/排序"的跨节点查询如何被拆分与归并。
  3. 识别一个查询计划里"该本地做却跨了网"的浪费点。

先看一句看着很简单的 SQL 有多难送

用户一句"统计每个用户的订单总额 TOP 10"。若数据分布在一百台节点,这句 SQL 对分布式优化器来说是个大难题:订单按用户 id 哈希分布着,"每个用户的前十"意味着得把所有节点都问一遍、再全网归并出真正的 TOP 10。规划器要干的事,就是把这句"全局视角"的 SQL 翻译成一份"给每个节点的施工单",并安排一台设备把各家答案拼回完整结果。

一、两级计划:全局与局部

全局计划是"面试时给考官看的大纲":结合数据分布(哪个分片在哪个节点)与元数据,把它拆成 ① 哪些子查询送到哪些节点 ② 谁来归并。局部计划是每个节点拿到自己的那块后的执行细节:本节点怎么扫、怎么过滤、怎么排序。规划器不是想当然拍板,它要基于"分片键、表大小、统计信息"来估算"每步要跨几次网络、搬多少数据",从而挑出最省的一种拆法。

分布式计划的层次

二、拆分与归并,用一个 TOP 示例看穿

假设我们要算"全网订单货值十佳用户"。规划器会这么拆:

1 给每个节点发子查询: 各节点只在本地算"本分片货值前10的用户" (因为全网前10一定躺在这些局部前10里,但局部前10不超过每个节点的top) 2 各节点把本地的 top10 上报给汇总节点 3 汇总节点把 N 个 top10 合并(至多 N×10 条),再做一次排序,取全球前10 ——注意这里没把全表搬上来,只搬了 N×10 条,这才是省的地方

这个示例里最值钱的优化是第 1 步的"先各算局部 top10"——它让网络只搬"候选的前十",而不是"每个节点的全部数据"。这正是查询规划里"能先在源头做掉的计算,就先在源头做掉"这条准则的体现。

三、糟糕的拆分长什么样

识别烂拆分的标志,无非三条:一是把不必要的整片数据搬上网,本可本地过滤的先全网汇总——看计划里有没有"全表搬移"剧就基本亮了;二是把聚合放到全网才做,本应先在各节点预聚合的 topN/求和却全部拉回汇总器;三是随心所欲地广播,能按分区键定位点路由的不去定位,硬是把一条单点查询放大成全网格卷。如果你的分布式库某个慢查询,去 EXPLAIN 一下,多半能在这些"该本地却跨网"的点上找到病根。

四、规划器到底在"算账"什么

当规划器在若干种拆法之间挑一个时,它其实是在对同一条 SQL 同时做三笔估算,而不是凭感觉。第一笔是搬运量——这条链路一共要跨几次节点、每次搬多少行多少列,单位通常按字节算;第二笔是本地成本——每个节点内部的扫描、排序、聚合大概要花多少 CPU 与 IO;第三笔是执行顺序——先过滤还是先联表,会不会因为顺序错导致中间结果暴涨。用一组假想数感受一下:一条"统计华南区近 30 天每人订单额前 20"的查询,若规划器把"华南区过滤"留在本地做,跨网上传的只有'命中区间的少数行',可能只有几百 KB;若它误把过滤放在全网汇总后才做,那全网订单(可能几个 GB)先被拉到汇总器才挡,无论是传输还是排序都是灾难级开销。同一个 SQL、两种拆法,性能差出两个数量级,差的完全不在 CPU,而在规划器有没有把"该算的账"算对。 这就是为什么凡是大厂分布式库,几乎都要维护一份尽量新鲜的统计信息(表大小、直方图、分片分布)喂给规划器——没有它,规划器就是瞎猜,算账也白算。

五、一张"拆法对了没有"的自查口诀

看完这些,你手上应该有一套能当场用的自查口诀,专治"这条 SQL 是不是没拆好":一问是否点路由能定——能按分区键直发的,别广播;二问过滤是否下推——WHERE 该在源头筛掉的,别等到全网才筛;三问聚合是否预聚合——topN 该各片先算一遍的,别全拉回汇总器才算;四问排序是否错位——要全局有序的,看各片那步是不是在拖不必要的量。把 EXPLAIN 输出的执行计划对着这四问过一遍,绝大多数慢查询的"拆错了"病根都能一眼揪出来。这也是你从"会看概念"走向"会调优"的一道关键台阶——看懂一份执行计划,比背十条优化口诀都顶用。

六、把这一节收回一句能带走的话

规划的内容不少,但真正值得你记住的其实就那么一句:"能先在源头算掉的,就先在源头算掉;能不搬的,就别搬。" 分布式查询规划的所有技巧,都是这句话的展开。

顺着想下去,规划器真正值钱的地方,不在它懂多少花哨算法,而在于它会拿着分片信息和统计,去"估"每一步要跨几次网、搬多少行——这套估算能力,才是好规划和烂规划差出数量级的根子。同样一句 SQL,规划器算出"A 拆法只搬几百 KB、B 拆法要搬几个 GB",于是它选 A,就这么简单。

作为会用分布式库的人,你能带走的行动,是把这句话送进每一次查看执行计划(EXPLAIN)的过程里:看到计划里哪一步"本可在源头做、却拖到了全网",就盯住它。这一盯,往往就把一条慢查询的病根抓住了——不是靠背参数,而是靠理解"规划在替你做搬与不搬的算术"。

本节要点回顾

  • 两级计划:全局拆分配汇总,局部定各节点执行。
  • 核心原则:能源头做掉就先做,只搬必搬之物。
  • TOP 示例:先各算局部 top10,再归并,网络只搬候选。
  • 三个病征:整片照搬、聚合全网做、无谓广播。

规划定了"谁在哪儿算",可"到底搬多少、怎么让数据更少动"才是省钱的深水区。下一节 7.2 讲数据传输与下推优化——谓词下推和列裁剪,怎么在源头上就把该搬的卡住。


作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U