MySQL中需用SELECT * FROM tbl PARTITION(pname)显式指定分区名才能确保只扫一个分区,SQL Server则需用WHERE $PARTITION.func(col)=n配合分区函数;二者均不可依赖WHERE条件替代,须查INFORMATION_SCHEMA.PARTITIONS或sys.partitions确认分区名或编号。
MySQL 中用 PARTITION 关键字查指定分区数据
mysql 支持在 select 语句中显式指定分区名,跳过其他分区直接读取目标分区,这是真正「只扫一个分区」的物理级过滤,不是 where 条件下推后的逻辑裁剪。
常见错误是以为加了 WHERE 就等于走分区——其实没加 PARTITION(p2023),优化器仍可能扫描多个分区(尤其当分区键函数不可下推时,比如 YEAR(create_time) 在某些版本中无法被准确识别)。
- 必须确保表已按
RANGE、LIST或HASH分区,且分区名明确(如p2023、p_q1) - 语法是
SELECT * FROM orders PARTITION(p2023),不能写成PARTITION = 'p2023'或放在WHERE里 - 不支持子查询或
UNION中嵌套PARTITION;也不支持对视图使用该语法 - 执行
EXPLAIN PARTITIONS可验证是否真的只访问了目标分区——输出中的partitions列应只显示一个名字
SQL Server 中用 $PARTITION 函数定位并过滤分区
SQL Server 没有类似 MySQL 的 PARTITION(p2023) 语法,而是靠 $PARTITION 函数把值映射到分区号,再结合 $PARTITION.myFunc(column) 在 WHERE 中做过滤。
容易踩的坑是混淆「分区号」和「分区边界值」:函数返回的是从 1 开始的整数编号(比如第 3 个分区),不是你定义的 VALUES (1000, 2000, 3000) 那些值。
- 先确认分区函数名,比如
myPartitionFunction,再写WHERE $PARTITION.myPartitionFunction(Id) = 2 - 不能直接写
WHERE Id IN (SELECT ... FROM sys.partitions)—— 这不会利用分区消除,仍是全表扫描 - 若分区列上有索引,且查询条件能覆盖分区键,SQL Server 通常自动做分区消除;但显式用
$PARTITION是唯一能强制只查某一分区的方式 - 注意分区号会随
SPLIT/MERGE操作变动,硬编码分区号的脚本需同步维护
查不到分区名?先从 INFORMATION_SCHEMA.PARTITIONS 或 sys.partitions 找
不知道分区叫什么,就别硬写 PARTITION(p2023) 或瞎猜分区号——大概率报错或查空。
MySQL 下查分区名最稳的方式是查 INFORMATION_SCHEMA.PARTITIONS,SQL Server 则要连查 sys.partitions 和 sys.destination_data_spaces。
- MySQL:
SELECT PARTITION_NAME, PARTITION_DESCRIPTION FROM INFORMATION_SCHEMA.PARTITIONS WHERE TABLE_NAME = 'orders' - SQL Server:
SELECT p.partition_number, dds.destination_id FROM sys.partitions p JOIN sys.destination_data_spaces dds ON p.partition_number = dds.destination_id WHERE p.object_id = OBJECT_ID('myPartitionedTable') - PostgreSQL 用户注意:这里不适用——它用
tableoid或pg_partition_tree,和 MySQL/SQL Server 完全不同路子 - 别依赖
SHOW CREATE TABLE查分区名:它只显示建表语句,不反映当前实际分区结构(比如已ALTER TABLE ... REORGANIZE PARTITION过)
为什么不能只靠 WHERE 条件“代替”分区筛选?
因为分区裁剪(partition pruning)不是 100% 可靠——它依赖优化器能否静态推断出 WHERE 条件必然落在某一分区。一旦表达式含函数、变量、隐式转换或跨列计算,裁剪就失效。
例如:MySQL 中 WHERE DATE(create_time) = '2023-01-01' 通常无法触发分区裁剪,而 PARTITION(p2023) 是绕过优化器、直奔物理存储的确定性操作。
- SQL Server 中
WHERE Id > @min AND Id 若 @min/@max 是参数,也可能导致分区消除失败(尤其是简单参数化场景) - 线上慢查排查时,第一反应不该是“加索引”,而是先看
EXPLAIN PARTITIONS或SET STATISTICS XML ON输出里的Actual Partition Count - 分区名或分区号写错时,MySQL 报
Unknown partition,SQL Server 报Invalid partition number——这两个错误信息就是最直接的线索
分区筛选这事,表面是语法问题,底层是优化器能力与物理存储路径之间的信任边界。写死分区名最快,但也最脆弱;依赖自动裁剪更省心,却容易在某个函数调用后突然变慢。真要稳,得两者配合着用。

















