需查看执行计划中的partitions列(mysql)或partition pruning字样(postgresql),确认实际访问分区是否与where条件匹配,而非依赖rows估算或界面默认显示。

怎么看执行计划里有没有走分区剪枝
Navicat 本身不直接显示「是否命中分区剪枝」,它只是把 MySQL 或 PostgreSQL 返回的执行计划原样展示出来。真正判断剪枝是否生效,得盯住 EXPLAIN 输出里的 partitions 列(MySQL)或 Partition Filter / Partition Key 相关信息(PostgreSQL)。如果你在 Navicat 的「查询」窗口执行 EXPLAIN SELECT ... 后只看到 id、type、rows 这些字段,大概率是没选对数据库类型,或者没开扩展显示。
- MySQL 用户:必须确保
EXPLAIN FORMAT=TREE或传统格式下显式包含partitions列 —— Navicat 默认可能隐藏该列,右键结果表头 → 「选择列」→ 勾选partitions - PostgreSQL 用户:用
EXPLAIN (ANALYZE, VERBOSE),重点看输出中是否出现Partition Pruning字样,以及Actual Partitions Searched数量是否远小于总分区数 - 别直接信
rows估算值:分区表的rows是按单个分区统计后叠加的,数值小≠剪枝成功;得看partitions列实际列出的分区名(如p202301,p202302)是否恰好是你 WHERE 条件覆盖的范围
WHERE 条件写法直接影响剪枝能否触发
分区剪枝不是智能匹配,它依赖优化器能静态推断出条件与分区表达式的等价关系。哪怕语义完全一样,换一种写法就可能失效。
- ✅ 有效写法(MySQL LIST/RANGE):
WHERE dt = '2023-01-01'、WHERE year(created_at) = 2023(前提是按year(created_at)分区) - ❌ 失效写法:
WHERE DATE(created_at) = '2023-01-01'(函数作用于分区字段会阻止剪枝)、WHERE created_at BETWEEN ? AND ?用变量参数时,Navicat 预编译可能让优化器无法确定范围 - ⚠️ 隐式类型转换也危险:
WHERE partition_col = 202301(int)vs 分区列为CHAR(6),会导致全分区扫描 - 测试技巧:在 Navicat 中先用具体字面量(如
'2023-01-01')跑EXPLAIN,确认剪枝正常后再换参数化查询
Navicat 查询窗口执行 EXPLAIN 的实操细节
Navicat 的「执行」按钮默认运行 SQL 不返回执行计划,必须手动加 EXPLAIN 前缀,且注意不同数据库语法差异。
- MySQL:直接写
EXPLAIN FORMAT=TREE SELECT * FROM orders WHERE dt = '2023-01-01';,结果在下方「结果」面板;若用传统格式,右键列头打开partitions列 - PostgreSQL:必须用
EXPLAIN (ANALYZE, BUFFERS, VERBOSE),否则看不到分区裁剪细节;Navicat 对VERBOSE输出支持良好,但需注意结果以文本块形式呈现,不是表格 - 避免踩坑:不要在 Navicat 的「设计表」或「数据」页点「筛选」——那走的是客户端过滤,和分区剪枝无关;所有分析必须通过「查询」窗口执行原生
EXPLAIN - 对比验证:改一次 WHERE 条件,复制粘贴两次
EXPLAIN语句并排查看partitions列变化,比单次分析更直观
为什么明明条件对得上,partitions 却显示 all?
这通常不是 Navicat 的问题,而是底层数据库未启用剪枝能力或配置有误,容易被误判为工具限制。
- MySQL 检查:
SELECT @@sql_mode;是否含NO_ENGINE_SUBSTITUTION等影响优化器行为的模式;分区表引擎必须是InnoDB(MyISAM 不支持剪枝) - PostgreSQL 检查:
SET enable_partition_pruning = on;(9.6+ 默认开启,但某些旧集群可能被关掉);子分区嵌套过深(如 RANGE-LIST 二级分区)可能导致剪枝退化 - 时间字段陷阱:MySQL 中用
DATETIME分区但查询条件传入TIMESTAMP字面量,或时区设置不一致(@@time_zone),会让优化器放弃推断 - 最硬核验证:在命令行连同数据库执行相同
EXPLAIN,如果命令行也显示all,说明问题不在 Navicat,而在表结构或查询本身
实际调优时,分区剪枝的边界很窄——差一个括号、少一个类型声明、甚至客户端连接时区不对,都可能让几十个分区变成全扫。别依赖 Navicat 的界面提示,盯死 partitions 列的具体值,才是唯一靠谱的方式。











