资讯详情

Mysql为什么选择走全表/索引:内核查询成本计算规则

trace工具的介绍

使用方式

‐‐ 开启trace SET optimizer_trace="enabled=on"; -- 查询数据 select * from file_info where file_name > 'a' order by create_time; -- 查看trace信息 SELECT * FROM information_schema.OPTIMIZER_TRACE; 

常见的trace字段信息

  • “join_preparation”: ‐‐第一阶段:SQL准备阶段,格式化sql
  • “join_optimization”: ‐‐第二阶段:SQL优化阶段
  • “condition_processing”: ‐‐条件处理
  • “table_dependencies”: ‐‐表依赖详情
  • “rows_estimation”: ‐‐访问预估表的成本
  • “table_scan”: ‐‐全表扫描
  • “potential_range_indexes”: ‐‐查询可用索引
  • “index”: “PRIMARY”, ‐‐主键索引
  • “index”: “idx_name_age_position”, ‐‐辅助索引
  • “analyzing_range_alternatives”: ‐‐各索引使用成本分析
  • “rowid_ordered”: false, ‐‐使用索引获得的记录是否按主键排序
  • “index_only”: false, ‐‐是否使用覆盖索引
  • “rows”: 5061, ‐‐索引扫描行数
  • “cost”: 6074.2, ‐‐索引使用成本
  • “chosen”: false, ‐‐是否选择索引
  • “best_access_path”: ‐‐最佳访问路径
  • “considered_access_paths”: ‐‐访问路径的最终选择
  • “access_type”: “scan”, ‐‐访问类型:为scan,全表扫描
  • “chosen”: true, ‐‐确定选择
  • “join_execution”: ‐‐第三阶段:SQL执行阶段

最后选择方法

  • 从索引中选择全表扫描cost值最小的一种进行执行

一条sql会产生什么成本?

单表查询的成本

  • 在单表查询句真正执行之前,MySQL查询优化器将找到所有可能使用的解决方案,并比较成本最低的解决方案。成本最低的解决方案是所谓的执行计划,然后调用存储引擎提供的接口进行真正的执行查询。

单表查询的索引选择过程

  • 根据搜索条件,找出所有可能使用的索引:possible keys
  • 计算全表扫描的成本:I/O成本(扫描页数)* 1.0 1.1(固定值) CPU成本(行数) * 0.2 1.0(固定值)
  • 用不同索引计算查询的成本
  • 比较各种执行方案的成本,找出成本最低的

记录行数的全表扫描值从何而来?

  • MySQL维护一系列统计信息!

  • 使用 SHOW TABLE STATUS 语句来查看表的统计信息 统计信息.png

  • 得到的Rows列信息:用于使用MyISAM对于存储引擎的表,值是准确的,用于使用InnoDB对于存储引擎表,该值为估计值。

  • Data_length:表示占用的存储空间字节数。

  • MyISAM对于存储引擎的表,值是数据文件的大小。
  • 对于使用InnoDB对于存储引擎的表,该值相当于聚簇索引占用的存储空间大小,即可以这样计算该值的大小: Data_length = 聚簇索引的页面数量 x 每个页面的大小 我刚才的结果:49152 ÷ 16 ÷ 1024 = 3页
  • 全表扫描成本:87*0.2 1.1 3*1 1.0=90

用不同索引计算查询的成本

  • 范围间隔数:连续范围IO成本就是1。
  • in的数量:in每个字符都是一个范围。也就是说,in每个记录都是一次回表。
  • 需要返回表的记录数:在此范围内估计返回表的次数。mysql5.7版本中涉及的页面小于10页,计算准确;如果涉及的页面数据超过10页,则进行估计(估计前10页的记录行数,可以找到多少页B 书的上一级)!每行回表都是一次记录!MySQL回表操作评估I/O成本仍然非常简单和粗糙,他们认为每个回表操作相当于访问一个页面;简单地说,有多少记录,几次回表。
  • 回表操作后获得的完整用户记录,然后检查其他搜索条件是否成立。cpu匹配。

in处理参数过多

  • 查看in参数精确匹配的个数值(MySQL 5.7.21中默认200): show variables like ‘%dive%’;
  • in超过这个参数eq_range_index_dive_limit值:估计一个值的重复次数 ≈ Rows(全表扫描估计行数) ÷ Cardinality(show index from 查询的当前索引Cardinality和)。然后用估算值乘以当前值in格式是实际计算值。

连接查询成本

  • 连接查询总成本 = 单访问驱动表的成本 驱动表扇出数 x 单次访问驱动表的成本
  • 扇出:查询驱动表后获得的记录条数
  • 计算方法的细节与单表相同!

结束语

  • 获得更多有价值的文章,让我们一起成为架构师!
  • 关注微信官方账号可以让你逐渐对准MySQL并发编程有更深入的理解!
  • 这个微信官方账号,没有广告!!!每天更新!

标签: 6074连接器

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台