优化器的作用:
我们知道,一条SQL语句,可以有很多执行方式,最后都返回相同的结果,而优化器的作用就是找到最好的执行计划。
一、RBO-基于规则的优化器(rule)
系统内置的一套硬编码规则,根据规则生成执行计划,无论表数据发生怎样的变化,也不会影响执行计划,也就是是RBO对数据不敏感;比如在规则中,索引的优先级大于全表扫描
二、CBO-基于成本的优化器(cost)
CBO优化器根据SQL语句生成一组可能被使用的执行计划,估算出每个执行计划的代价,选择一个代价最小的执行计划。
三、Mysql的查询优化器
Mysql采用的是CBO-基于成本的优化器,它会尝试估算一个查询所有可能的执行计划的成本,并选择其中成本最小的一个执行计划。成本的最小单位是随机读取一个4K的数据页的成本;可以通过查询当前会话的Last_query_cost的值获取Mysql计算的当前查询的成本。如下:
EXPLAIN SELECT * FROM `user` WHERE username='xxxx';
SHOW STATUS LIKE 'Last_query_cost';
1、 常用的优化类型
(1)、重新定义关联表的顺序
数据表的关联并不总是按照在查询中指定的顺序执行。决定关联的顺序是优化器很重要的一部分功能。
(2)、将外连接转为内连接
并不是所有的outer join 语句都必须以外连接的方式执行。例如where条件、库表结构都可能会让外连接等价一个内连接。MySQL能够识别这点并重写查询,让其可以调整关联顺序。
(3)、使用等价变化规则;可以合并和减少一些比较,还可以移除一些恒成立和恒不成立的判断
MySQL可以使用一些等价变换来简化并规范表达式。它可以合并和减少一些比较,还可以移除一些恒成立和一些恒不成立的判断例如(8=8 and a>8)将被改写成 a>8。
(4)、优化count()、min()和max()
count(*)、count(1)由于统计没有明确的字段,所以查询以行数为准,不会判断某一列中的null值;
count(uid)则会判断uid列中的null值,并把null值排除。
对max、min统计频繁或数据量大的字段尽量添加索引,可以大大提高查询统计的效率。
(5)、预估并转化为常数表达式;当MySQL检测到一个表达式可以转化为常数时,就会一直把该表达式作为常数进行优化处理
(6)、覆盖索引扫描;当扫描的索引列包含所有查询中需要的使用的列时,MySQL就可以直接使用索引返回需要的数据。(explain分析extra值为use index)
2、关联查询排序优化
关联查询时使用排序,两种情况:
(1)、order by子句的所有排序列都来自关联的第一张表,mysql在关联处理第一个表时就会进行文件排序。
(2)、除上述(1)中情况之外,mysql都会将关联的结果存放在一个临时表中,在所有关联都结束之后,再进行文件排序。这点可以通过explain分析查询语句查看extra里面的内容验证。
(*)如果排序查询中有LIMIT的话,LIMIT也会在排序之后应用,所以即使需要返回较少的数据,临时表和需要排序的数据量仍然会非常大。
3、查询优化器提示
(1)DELAYED
对于 INSERT 和 REPLACE 有效。
mysql 会将提示语句立即返回给客户端, 并将插入的行数据放入到缓冲区, 然后在表空闲的时候批量将数据写入。Innodb不支持。
(2)STRAIGHT_JOIN
在数据量大的联表查询中灵活运用的话,直接影响关联顺序, 减少statistics(统计)的时间, 能大大缩短查询时间。 STRAIGHT_JOIN功能同join类似,但能让左边的表来驱动右边的表,能改表优化器对于联表查询的执行顺序。
(3)USE INDEX 、 IGNORE INDEX 、 FORCE INDEX
提示优化器使用不使用索引,USE INDEX 、 FORCE INDEX 使用基本一致,FORCE INDEX 更加强调全表扫描,代价更大。
4、什么时候该创建索引,实在无法决定,教你一招
索引选择性 = 基数/总行数
比如:有一张user表,对表中nickname字段计算索引选择性:
SELECT COUNT(DISTINCT(nickname))/COUNT(id) AS selectivity FROM user;
计算出selectivity的值就是选择性,最大为1,值越大,选择性越高,所以有时候索引的建立不仅跟表结构有关,还跟数据量结构和数据量有关。
好了,今天的分享就到这里,如果喜欢我的内容,欢迎收藏、转发~~
谢谢!下期见。。。