MySQL-一些问题
优化器未使用你想用的索引
|
|
前缀索引
|
|
count区别
MyISAM索引结构的优势count快就不说了而Innodb由于MVCC与可重复读的原因速度会相对慢点
count(*)、count(主键id)和count(1) 都表示返回满足条件的结果集的总行数;而count(字段),则表示返回满足条件的数据行里面,参数“字段”不为NULL的总个数
对于count(主键id)来说,InnoDB引擎会遍历整张表,把每一行的id值都取出来,返回给server层。server层拿到id后,判断是不可能为空的,就按行累加。
对于count(1)来说,InnoDB引擎遍历整张表,但不取值。server层对于返回的每一行,放一个数字“1”进去,判断是不可能为空的,按行累加。
单看这两个用法的差别的话,你能对比出来,count(1)执行得要比count(主键id)快。因为从引擎返回id会涉及到解析数据行,以及拷贝字段值的操作。
对于count(字段)来说:
- 如果这个“字段”是定义为not null的话,一行行地从记录里面读出这个字段,判断不能为null,按行累加;
- 如果这个“字段”定义允许为null,那么执行的时候,判断到有可能是null,还要把值取出来再判断一下,不是null才累加。
但是count(*)是例外,并不会把全部字段取出来,而是专门做了优化,不取值。count(*)肯定不是null,按行累加
所以结论是:按照效率排序的话,count(字段)<count(主键id)<count(1)≈count(*),所以我建议你,尽量使用count(*)
Order By 排序流程
内存排序
当Extra这个字段出现Using filesort
表示的就是需要排序。
|
|
按name排序”可能在内存中完成,当参数sort_buffer_size
内存不够时,会使用临时文件辅助排序。
max_length_for_sort_data
是MySQL中专门控制用于排序的行数据的长度的一个参数。它的意思是,如果单行的长度超过这个值,MySQL就认为单行太大,要换一个算法。city、name、age 这三个字段的定义总长度是36
|
|
联合索引排序
并不是所有的order by语句,都需要排序操作的。从上面分析的执行过程,我们可以看到,MySQL之所以需要生成临时表,并且在临时表上做排序操作,其原因都是无序的,如果我们建立联合索引,保证天然有序就好了
|
|
Group By 分组优化总结
|
|
如果对group by语句的结果没有排序要求,要在语句后面加 order by null;
尽量让group by过程用上表的索引,确认方法是explain结果里没有Using temporary 和 Using filesort;能用索引肯定更好
如果group by需要统计的数据量不大,尽量只使用内存临时表;也可以通过适当调大
tmp_table_size
临时表大小参数,来避免用 到磁盘临时表;(group by语句中需要放到临时表上的数据量特别大,就会“先放到内存临时表,插入一部分数据后,发现内存临时表不够用了再转成磁盘临时表”)如果数据量实在太大,使用SQL_BIG_RESULT这个提示直接使用磁盘临时表,少去内存转临时的过程,来告诉优化器直接使用排序算法得到group by的结果。
select SQL_BIG_RESULT id%100 as m, count(*) as c from t1 group by m;
其实DISTINCT 跟group by 逻辑基本一样。也是采用临时表
- 创建一个临时表,临时表有一个字段a,并且在这个字段a上创建一个唯一索引;
- 遍历表t,依次取数据插入临时表中: 如果发现唯一键冲突,就跳过; 否则插入成功;
- 遍历完成后,将临时表作为结果集返回给客户端。
隐式转换
|
|
大表扫描200G数据问题
server层采用的是边读边发的操作。
|
|
- 一个查询在发送过程中,占用的MySQL内部的内存最大就是net_buffer_length这么大,并不会达到200G;
- socket send buffer 也不可能达到200G(默认定义/proc/sys/net/core/wmem_default),如果socket send buffer被写 满,就会暂停读数据的流程。
InnoDB引擎处理
由于冷热数据链的原因,大表扫描并不会影响young区域,只会占用old区域。
由于MySQL采用的是边算边发的逻辑,因此对于数据量很大的查询结果来说,不会在server端保存完整的结果集。所以, 如果客户端读结果不及时,会堵住MySQL的查询过程,但是不会把内存打爆。 而对于InnoDB引擎内部,由于有淘汰策略,大查询也不会导致内存暴涨。并且,由于InnoDB对LRU算法做了改进,冷数 据的全表扫描,对Buffer Pool的影响也能做到可控。 当然,全表扫描还是比较耗费IO资源的,所以业务高峰期还是不能直接在线上主库执行全表扫描。
刷脏抖动问题
|
|
RAID阵列的定期放电导致抖动问题
写脚本自动在凌晨低峰时自动放电
连接数不够
先看看 linux 本身的连接数 再看 mysql 的连接数