分区键选错会导致group by完全失效,因无where条件时全分区扫描反而更慢;正确做法是where必须基于分区键过滤以触发分区裁剪,且复合索引需将分区键置于最左。

分区键选错会导致GROUP BY完全失效
分区表对聚合查询提速的前提是:WHERE条件能触发分区裁剪(Partition Pruning),而GROUP BY字段是否在分区键上,反而不是关键。真正要命的是——如果查询没在分区键上加过滤条件,数据库会扫描所有分区,此时分区表比普通表还慢(额外有元数据开销)。
- 错误写法:
SELECT category, SUM(amount) FROM sales GROUP BY category—— 没WHERE,全分区扫描 - 正确写法:
SELECT category, SUM(amount) FROM sales WHERE sale_date >= '2024-01-01' GROUP BY category—— 假设sale_date是分区键,数据库只读p2024分区 - 常见陷阱:把
category设为分区键,但业务查询几乎从不按category过滤,导致每次都是全分区扫描
复合索引必须包含分区键才能加速分组
即使做了分区,如果GROUP BY字段没索引,或索引没覆盖查询所需列,照样要排序或临时表,分区带来的收益会被抵消。
- 推荐建法:
CREATE INDEX idx_sale_date_category_amount ON sales (sale_date, category) INCLUDE (amount)—— 分区键sale_date放最左,GROUP BY字段紧随其后,INCLUDE把聚合字段拉进索引避免回表 - 别用
INDEX (category, sale_date):顺序反了,无法利用分区裁剪,sale_date变成范围扫描而非精准定位 - SQL Server中
INCLUDE字段不能参与索引查找,但能减少KEY LOOKUP;MySQL 8.0+可用函数索引或前缀索引替代
GROUP BY + WHERE组合必须匹配分区策略
分区类型(RANGE/LIST/HASH)决定了WHERE怎么写才有效。写错一个符号,分区就白建了。
- RANGE分区(如按年/月):
WHERE sale_date BETWEEN '2024-01-01' AND '2024-12-31'✅;WHERE YEAR(sale_date) = 2024❌(函数导致无法裁剪) - LIST分区(如按地区编码):
WHERE region IN ('BJ', 'SH', 'GZ')✅;WHERE region LIKE 'B%'❌(模糊匹配无法裁剪) - HASH分区(如按user_id哈希):
WHERE user_id = 12345✅;WHERE user_id > 10000❌(范围查询无法定位单个分区)
EXPLAIN里看不到“partitions”字段说明裁剪失败
执行计划是唯一真相。哪怕你写了WHERE、建了索引、分区也分好了,只要EXPLAIN输出里partitions列显示NULL或all,就等于没生效。
- MySQL查法:
EXPLAIN PARTITIONS SELECT ...,重点看partitions列是否只列出1–2个分区名 - SQL Server查法:看执行计划XML里的
PartitionCount和ActualPartitionCount是否一致且远小于总分区数 - 容易忽略的干扰项:
FORCE INDEX可能绕过分区裁剪;UNION ALL子查询若没对齐分区键,各分支仍可能扫全表











