EXPLAIN PARTITIONS 显示 partitions: NULL 表明分区裁剪完全失效,主因是WHERE条件对分区键使用函数、分区键未纳入主键或唯一索引、查询未包含分区键、UNIX_TIMESTAMP跨时区导致数据落入未定义分区,或TO_DAYS边界值未对齐自然月起始日。

能显著提升,但前提是分区键参与查询、主键包含该字段、且写法严格符合剪枝规则——否则比普通表还慢。
为什么 EXPLAIN PARTITIONS 显示 partitions: NULL?
这是分区完全失效的明确信号,常见原因有:
-
WHERE条件里对分区字段用了函数,比如WHERE YEAR(log_time) = 2024或WHERE DATE_FORMAT(log_time, '%Y-%m') = '2024-01',优化器无法推导边界 - 分区字段(如
log_time)没包含在主键或任何唯一索引中——MySQL 5.7+ 会建表失败;低版本虽能建,但查询时无法剪枝 - 查询条件完全不涉及分区键,例如只用
WHERE app_id = 1001,而分区键是log_time,此时所有分区都要打开扫描 - 建表时用了
UNIX_TIMESTAMP()且跨时区插入数据,导致值落在未定义分区里,触发 fallback 到全分区扫描
怎样写 TO_DAYS() 分区才不报错也不失效?
关键在于整数转换必须对齐自然月起始日,且边界值必须是完整日期字符串:
安装、修复、更新或打包一个基于 Python 和 PyMySQL 实现的 Windows `mysql` 命令。适用于用户希望在 PowerShell/CMD 中输入 `mysql` 时重定向到 Python 实现、需要交互式输入 MySQL 连接信息、需要同步到当前用户本地 bin 目录,或需要将该能力封装成可公开复用的 Codex skill。
- 错误写法:
LESS THAN (TO_DAYS('2026-05'))→ 报语法错误;LESS THAN (TO_DAYS('2026-05-31'))→ 实际覆盖的是 5 月 30 日前,造成数据错位 - 正确写法:
LESS THAN (TO_DAYS('2026-06-01'))表示“2026 年 5 月及之前”,边界清晰、可预测 - 必须保留
p_future分区:当前是 2026-10-15,p_future的LESS THAN MAXVALUE必须存在,否则插入 2026-11 数据会直接报ERROR 1526 (HY000): Table has no partition for value - 主键必须是联合主键:例如
PRIMARY KEY (id, log_time);单列PRIMARY KEY (id)在 MySQL 5.7+ 下建表会被拒绝
查最近 N 天加 ORDER BY LIMIT 为啥更慢?
分区剪枝只解决“扫哪些分区”,不解决“每个分区内怎么查”。当满足以下任一条件时,性能反而下降:
- 每个分区内部没有针对
log_time的二级索引,ORDER BY log_time DESC LIMIT 20只能在各分区分别排序再归并,开销翻倍 - 分区太多(比如按天分了 365 个),即使只扫最近 7 个分区,也要打开 7 个 .ibd 文件,产生额外元数据和文件句柄开销
-
log_time上没建索引,或索引不是最左前缀,导致每个分区都走全表扫描 + filesort - 使用 MyISAM 引擎:即使只扫 2 个分区,也会打开全部分区文件(MyISAM 设计限制),文件描述符耗尽风险陡增
真正起效的组合是:按月 RANGE 分区 + log_time 在主键中 + 每个分区内部有覆盖索引 + 查询条件带精确时间范围。漏掉任意一环,分区就只是徒增运维负担。










