MySQL如何对一个查询语句的多个查询计划评估他的成本的?
(1)成本计算: CPU成本 和 IO 成本
简单来说,跑一个SQL语句,一般成本是两块,首先是那些数据如果在磁盘里,要从磁盘把数据读取出来,这个磁盘读数据到内存就是IO成本,而且根据MySQL里都是一页一页读的,读一页的成本约定为1.0
然后还有一个成本,拿到数据之后,需要对数据做一些计算,验证是否符合搜索条件,或者做一些排序分组之类的事,这些都是耗CPU资源的,属于CPU成本,一般约定读取和检测一条数据是否符合条件的成本是0.2
这个所谓1.0和0.2就是自定义的一个成本值,代表的意思就是一个数据页IO成本是1.0,一条数据检测的CPU成本就是0.2,然后 SQL语句
select * from t where x1=xx and x2=xx , 此时有两个索引,分别是针对x1,x2建立的,就会先看看这个SQL可以用到那个索引,此时发现x1和x2的索引都能用到,他们俩索引就是possible keys,接着会针对这个SQL计算一下全表扫描的成本,这个全表扫描是需要先磁盘IO聚簇索引里的叶子节点上的数据一页页读到内存,这有多少数据页就得耗费多少IO成本,接着对内存里的每一条数据都判断是否符合搜索条件,这有多少数据就要耗费多少CPU成本。
所以此时就得计算这块的成本是多少, show table status like ‘表名’,可以拿到表的统计信息,对表进行增删改时候,MySQL会维护这个表的一些统计信息,比如这里可以看到rows和data_length 两个信息,对于innodb 来说,这个rows是估计值。
rows就是表里的记录数, data_length 就是表的聚簇索引的字节数大小,此时用data_length 除以1024 就是kb为单位的大小,然后再除以 16KB ,就是有多少页,此时知道数据页的数量和rows记录数,就可以计算全表扫描成本。
(2)总结:
IO成本: 数据页数量1.0 + 微调值
CPU成本: 行记录数0.2+微调值, 两个相加就是一个总的成本之,比如有数据页100个,记录数有2万条,此时总成本值大致是 100+4000=4100,在这个左右