说得再花哨,"把过滤和裁剪尽量下推到数据所在节点"才是分布式查询省钱的真功夫。谓词下推让不满足条件的行在源头就被筛掉,列裁剪让无关的列根本不用离库,两者合力把跨节点传输量压缩到最小。本节用一支"购物车对账"的 SQL 演练把这两招跑通,并指出"下推失败"时传输量会膨胀到什么程度。
阅读完本节,你应当能够:
规划定了查询怎么拆,可拆分后的传输依然是最烧钱的一块。你也许觉得"多传点没关系,反正是机器之间"。但在分布式场景里,一次跨节点的数据搬家是"一个完整网络往返"量级的开销,比本机内存贵几个数量级。所以优化的第一课是:能少传就少传,能不入网就不入网。要达到"少传",主要靠两招——谓词下推与列裁剪。
所谓谓词,就是那些 WHERE 条件。谓词下推的意思很直白:别等到把所有该搬的数据都搬上网再过滤,而要把"是否满足条件"的判断,下推到数据真正所在的那个节点、尽早把不满足的行筛掉。例如"查最近 30 天、货值超一万的订单",正确做法是让每个节点在本地先按时间与金额过滤一遍,只把"命中"的行上网汇总,而不是把全网订单哗啦一声拉回来再筛。
列裁剪更不起眼,却常能省出可观的量。设想你有一个订单表,宽二十五列,可这次查询只用到"订单号、用户、金额"三列。如果傻乎乎地按行把整行搬走,等于给每个命中行都托运二十多列没用的大件。列裁剪让每台节点只把"查询真正需要的列"打包上传,宽列留在库底。对"列多、但查询只摘几列"的分析类负载,这一个裁剪动作就能把传输量砍掉一大半。
看一场实操,数据是"订单表(order_id,user_id,amount,created_at)"分片在某分布库,我要"未来 30 天华南区的应收与实收对账"。优化后的执行大概是这样:
1 下推过滤: 每个存储节点先本地筛 created_at 在该区间、且 region 属华南的行 -- 谓词下推: 时间与地区两个条件,都在源头筛掉 2 列裁剪: 只把对账需要的 金额 与 来源标记 两列打包上传 -- 其余宽列如备注、物流单号通通留在本地 3 汇总: 汇总节点对已压缩的子集做求和,得出应收与实收
第 1、2 步做完,网络实际搬运的只有"华南区、近30天、两列"——与"全网订单、全列"相比,可能差出两三个数量级。这就是"下推成功"和"下推失败"的分水岭:前者一个对账查完只几 KB,后者可能搬回几个 GB。
当优化器没能把谓词下推(常因统计信息陈旧、或表没有按查询条件分区),查询就退回"全表搬运"模式:全网数据先照搬往汇总器,汇总器再做本是源头该做的过滤。后果你很容易脑补——一个本该几十毫秒的对账,变成上百兆的搬运,把网络和汇总器一起拖垮。排查慢分布式查询时,先看 EXPLAIN 里有没有"全表搬移",若有,问题九成在"下推没下去"。给它压上正确的分区键与索引,让条件能直接在节点本地命中,通常就是解药。
把谓词下推和列裁剪再拎出来对比一下,你就知道它们各管一段、互为补充。谓词下推管"行":它在源头把不满足 WHERE 的行筛掉,省的是"行数",所以它对"命中率低的过滤条件"最见效——比如一个大表里只有 1% 的行是近 30 天华南区,下推直接让 99% 的行不用上路;列裁剪管"列":它在源头把用不到的列留库,省的是"每行的宽度",所以它对"宽表、查询只摘几列"的分析负载最见效——一张 40 列的日志表,查询只要其中 3 列,裁剪后每行至少少带十几列。一个减行数、一个减列宽,两者相乘才是最终的传输量。单独做哪个都行,一起做得最优——这也是为什么读一张统计报告里"传输量下降 95%"时,背后往往两个动作都在。
也坦诚地承认一点:下推并非万能,有几种情况你算得再漂亮也省不下来。一是查询条件没有落在分片键上:比如按"商品类目"过滤、但表是按"用户 id"分片的,过滤根本下不到源头,只能全表扫后再筛;二是统计信息严重过期:规划器误以为某条件命中极少,实际把它搬上网才发现是海量;三是命中率本来就高的列:如果 90% 的行都满足条件,下推省不了多少,传输体积由表本身决定。认清这些边界,你就不会在"为什么已经下了推还是慢"的问题上打转——先把"条件有没有落在分片键上"这一条排在前,很多悬案立刻有解。
下推和裁剪讲完了,再送你一个常在宽表上出现的加分技巧:只在路由时带"裁剪后的必要列",别带整行。 很多宽表有几十列,但路由和后续归并其实只需要少量字段。在接入层就把查询要的列清单带去,让每台节点只上传"命中行 + 必要列",等于把下推和裁剪一起提前到"数据还在源头"就生效。配上这句话理解:下推管行、裁剪管宽、路由管带——三个动作任何一环漏了,传输都会涨。你在 EXPLAIN 里把这三样都盯到位,慢查询就逃不出你的法眼。
过滤和裁剪能省出成捆的传输,可一旦查询要"把两张表按某个键拼起来",又是另一场输赢——这就要看 Join 策略怎么选了。下一节 7.3 讲 Broadcast、Shuffle、Colocation 三种 Join 各在什么时候最省钱。