当前位置: 首页
数据库
为什么SQL关联查询执行计划选择了全表扫描_分析统计信息过期

为什么SQL关联查询执行计划选择了全表扫描_分析统计信息过期

热心网友 时间:2026-04-29
转载

为什么SQL关联查询执行计划选择了全表扫描?

为什么SQL关联查询执行计划选择了全表扫描_分析统计信息过期

免费影视、动漫、音乐、游戏、小说资源长期稳定更新! 👉 点此立即查看 👈

问题的根源,往往不是你的SQL写得有问题,而是数据库优化器“觉得”走索引不划算。这个“觉得”背后,依赖的是一套可能已经过时的统计信息。无论是MySQL、PostgreSQL还是Oracle,优化器都需要依据表的行数、列的数据分布(比如基数cardinality)、索引页深度等数据来估算不同执行路径的成本。一旦这些统计信息没有及时更新,优化器就可能做出错误的判断。

一个典型的表现就是:明明关联字段上创建了索引,但EXPLAIN的结果却显示type: ALL(MySQL)或Seq Scan(PostgreSQL)。更明显的信号是,rows列的估算值与实际值严重不符,比如估算扫描100行,实际却有50万行。

  • MySQL:执行ANALYZE TABLE t1会重新采样数据,并更新information_schema.STATISTICSmysql.innodb_table_stats中的信息。
  • PostgreSQL:执行ANALYZE t1会更新pg_statistic系统表。需要注意的是,它的自动分析通常只在表的数据修改量超过一定阈值时才触发,大表可能长期得不到更新。
  • Oracle:需要显式调用DBMS_STATS.GATHER_TABLE_STATS过程。建议将ESTIMATE_PERCENT参数设为DBMS_STATS.AUTO_SAMPLE_SIZE,以获得更可靠的统计。

哪些操作后必须手动 ANALYZE

统计信息的更新并非实时同步。尤其是在数据发生剧烈变动后,旧的统计信息会立刻失效,导致执行计划劣化。以下几种场景几乎必然需要手动更新统计信息:

  • 执行了TRUNCATE或大批量DELETE操作(例如删除了表中80%的数据),之后没有跟进ANALYZE
  • 使用LOAD DATA INFILECOPY命令导入了百万级别以上的新数据。
  • 对某一列进行了大量倾斜写入(例如,短时间内新增了10万条status = 'pending'的记录,但统计信息里还认为该列的值是均匀分布的)。
  • 数据库小版本升级后首次启动(部分版本会重置统计信息缓存)。

JOIN 字段有索引却未被选用:检查三件事

遇到这种情况,先别急着删除索引或重写SQL。不妨按顺序排查以下三点,确认是否是过时的统计信息误导了优化器:

  • 核对真实行数:执行SELECT COUNT(*) FROM t1 WHERE join_col = 'x',将结果与EXPLAIN输出中的rows估算值对比。如果两者相差10倍以上,那么统计信息不准的可能性就非常大。
  • 评估索引选择性:计算SELECT COUNT(DISTINCT join_col) / COUNT(*) FROM t1。如果结果低于0.01(意味着超过99%的值是重复的),那么即使有索引,优化器也很可能选择放弃使用它——这是一个基于成本的合理判断,并非系统bug。
  • 确认索引覆盖:对于WHERE t1.a = t2.b这样的关联条件,需要确保t1表上有INDEX(a),t2表上有INDEX(b)。缺少其中任何一个,另一张表就可能被迫进行全表扫描来完成关联。

生产环境 ANALYZE 的风险与折中

对全表执行ANALYZE在大表上可能带来风险:例如在部分版本中会锁表(MySQL 5.7+多数情况不锁,但可能加读锁),并消耗大量I/O资源。因此,绝对要避免在业务高峰期执行。更稳妥的做法是:

  • 对大表采用采样分析:在MySQL 8.0+中,可以使用ANALYZE TABLE t1 UPDATE HISTOGRAM ON join_col WITH 16 BUCKETS这样的命令,只对关键列生成直方图统计,速度比全量分析快5到10倍。
  • 调整统计精度:在PostgreSQL中,可以适当提高default_statistics_target参数的值(例如从默认的100设为200),以提升关键列的统计信息精度,再配合定期的ANALYZE任务。
  • 注意操作位置:应避免在从库上执行ANALYZE(MySQL从库默认关闭统计信息收集,PostgreSQL从库禁止写入操作)。所有更新统计信息的操作都应在主库完成。

最后,还有一个最容易被忽略的盲点:许多ORM框架(例如Django的bulk_create)或ETL工具在批量插入数据后,并不会自动触发统计信息的更新。这不能指望开发人员每次都记得手动补上,而必须在运维侧建立配套的、定期的ANALYZE任务来保障。

来源:https://www.php.cn/faq/2391216.html

游乐网为非赢利性网站,所展示的游戏/软件/文章内容均来自于互联网或第三方用户上传分享,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系youleyoucom@outlook.com。

同类文章
更多
Oracle分区表物化视图如何支持高并发_优化锁资源竞争

Oracle分区表物化视图如何支持高并发_优化锁资源竞争

Oracle物化视图FAST REFRESH默认锁整分区表,因物化视图日志缺失分区键信息,无法定位变更分区;需同时满足日志含分区键列且MV定义显式引用该列,才能实现分区粒度加锁。 物化视图刷新时为什么会锁定整个分区表? 许多Oracle DBA都曾面临一个典型问题:在执行分区表的物化视图FAST R

时间:2026-04-29 19:49
如何处理SQL语句中的HEX编码注入绕过_对输入流进行16进制检测

如何处理SQL语句中的HEX编码注入绕过_对输入流进行16进制检测

HEX编码绕过:当十六进制字面量成为SQL注入的“隐身衣” 在安全对抗的战场上,攻击者的手法总是层出不穷。其中,利用十六进制(HEX)编码绕过传统的关键字和符号过滤,已经成为一种相当经典且有效的SQL注入手段。这背后的原理并不复杂,但防御起来却需要格外细致的考量。 HEX编码在SQL注入中怎么被用来

时间:2026-04-29 19:49
Oracle RMAN备份加密如何配置_通过配置备份加密增强安全性

Oracle RMAN备份加密如何配置_通过配置备份加密增强安全性

RMAN备份加密:那些容易被忽略的配置陷阱与性能真相 说到RMAN备份加密,一个常见的误解是“配置了就能自动生效”。事实并非如此,关键在于必须清晰区分configure encryption for database on(全局策略)和set encryption on identified by(

时间:2026-04-29 19:48
SQL怎样实现类似Excel透视表的功能_利用CASE WHEN行转列

SQL怎样实现类似Excel透视表的功能_利用CASE WHEN行转列

SQL怎样实现类似Excel透视表的功能_利用CASE WHEN行转列 SQL里用CASE WHEN做行转列,本质是聚合+条件判断 开门见山,先说核心:CASE WHEN这个语句本身并不产生“转列”的魔法。它必须和GROUP BY以及聚合函数(比如SUM、COUNT)联手,才能模拟出Excel透视表

时间:2026-04-29 19:48
如何解决ORA-12541无监听程序_lsnrctl status排查流程

如何解决ORA-12541无监听程序_lsnrctl status排查流程

ORA-12541 连接失败深度解析:监听器未启动是主因,系统化排查从状态检查到网络验证 ORA-12541 报错时,先确认监听器进程是否真的在运行 当数据库连接出现 ORA-12541 错误时,许多用户会首先怀疑 tnsnames ora 配置或服务名设置。实际上,该错误的根本原因在于客户端无法与

时间:2026-04-29 19:48
热门专题
更多
刀塔传奇破解版无限钻石下载大全 刀塔传奇破解版无限钻石下载大全
洛克王国正式正版手游下载安装大全 洛克王国正式正版手游下载安装大全
思美人手游下载专区 思美人手游下载专区
好玩的阿拉德之怒游戏下载合集 好玩的阿拉德之怒游戏下载合集
不思议迷宫手游下载合集 不思议迷宫手游下载合集
百宝袋汉化组游戏最新合集 百宝袋汉化组游戏最新合集
jsk游戏合集30款游戏大全 jsk游戏合集30款游戏大全
宾果消消消原版下载大全 宾果消消消原版下载大全
  • 日榜
  • 周榜
  • 月榜
热门教程
更多
  • 游戏攻略
  • 安卓教程
  • 苹果教程
  • 电脑教程