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会产生什么成本?
- :经常使用我们的手表MyISAM、InnoDB存储引擎将数据和索引存储在磁盘上。当我们想查询表中的记录时,我们需要在操作前将数据或索引加载到内存中。从磁盘到内存的加载过程中损失的时间称为I/O成本。
- :读取和检测记录是否符合相应的搜索条件,对结果集进行排序等操作损失的时间称为CPU成本。
- 对于InnoDB在存储引擎方面,页面是磁盘与内存交互的基本单位,MySQL读一页的成本默认为1.0.默认读取和检测记录是否符合搜索条件的成本.2
单表查询的成本
- 在单表查询句真正执行之前,MySQL查询优化器将找到所有可能使用的解决方案,并比较成本最低的解决方案。成本最低的解决方案是所谓的执行计划,然后调用存储引擎提供的接口进行真正的执行查询。
单表查询的索引选择过程
- 根据搜索条件,找出所有可能使用的索引:possible keys
- 计算全表扫描的成本:I/O成本(扫描页数)* 1.0 1.1(固定值) CPU成本(行数) * 0.2 1.0(固定值)
- 用不同索引计算查询的成本
- 比较各种执行方案的成本,找出成本最低的
记录行数的全表扫描值从何而来?
-
MySQL维护一系列统计信息!
-
使用 SHOW TABLE STATUS 语句来查看表的统计信息
-
得到的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并发编程有更深入的理解!
- 这个微信官方账号,没有广告!!!每天更新!