菜单 学习猿地 - LMONKEY

VIP

开通学习猿地VIP

尊享10项VIP特权 持续新增

知识通关挑战

打卡带练!告别无效练习

接私单赚外块

VIP优先接,累计金额超百万

学习猿地私房课免费学

大厂实战课仅对VIP开放

你的一对一导师

每月可免费咨询大牛30次

领取更多软件工程师实用特权

入驻
143
0

mysql学习总结

原创
05/13 14:22
阅读数 29147
mysql精讲(从mysql底层源码解析)
1.基于计算机的局部性原理,从磁盘经过io将数据存到内存中,一次取1页数据(4kb大小);
 
2.如a字段为自增张主键,在插入的时候,其实就按照顺序插入,虽然会影响插入性能,但是会提升查询性能;
 
3.
mysql索引
 
覆盖索引以及回表:
如果查询内容是索引及pk(主键)的子集,此时就是覆盖索引,不需要回表查询其他字段了。
 
前缀索引:指的是定义字符串的一部分作为索引。
优点:节省空间
缺点:会增加扫描次数,并且不能使用覆盖索引(区分度不够)
 
 
mysql什么情况下会放弃索引:
1.如果对字段做了函数计算,就用不上索引了,但是如果是对索引字段的参数,如下面的7用函数,这样就可以用上索引了
eg: where month(create_time) = 7;
 
2.隐式类型转换:
eg: 如tradeid为字符串类型。当为如下查询时
select * from log where tradeid = 1;
-----由于输入的参数是整型,所以需要做类型转换,此时会做全表扫描,放弃了索引。
详解:(在mysql中,字符串和数字做比较的话,是将字符串转换成数字)
对于优化器来说,相当于:
select * from log where CAST(tradeid as signed int) = 1;
也就是说,这条语句触发了我们上面说到的规则:对索引字段做函数操作,优化器会放弃走树搜索功能。
 
但是:select * from tradelog where id="1"; ---仍然会走索引。
详解:如果输入的类型和字段类型不一致,如字段为字符串类型,由于很多不同的字符串都可以转化为
1,如:'1',' 1'或 '1a'。但是本身是int型,转化成字符串是唯一的,所以会用到索引。------总结:看的是:字段类型转化的是不是唯一的
 
 
 
3.连表查询表的字符集不一致,即使连表字段加上了索引也会不起作用。
eg: select d.* from tradelog l, trade_detail d where d.tradeid=l.tradeid and l.id=2;
其中tradelog字符集为utf8mb4,trade_detail字符集为utf8
方法1:使用convert()函数临时将字符集转换成一致;
方法2:转换trade_detail字段的字符集为utf8mb4或者将整张表字符集为utf8mb4;
 
另外utf8mb4是utf8的超集,所以当这两个类型的字符串进行比较的时候,mysql内部操作是,先把utf8字符串转化成utf8mb4字符集
关键在于第三步由于字符集不同,拆分后等同于下面的写法:
select * from trade_detail where CONVERT(traideid USING utf8mb4)=$L2.tradeid.value;
这就再次触发了我们上面说到的原则:对索引字段做函数操作,优化器会放弃走树搜索功能
即:连接过程中在被驱动表的索引字段上加上函数操作,导致被驱动表做全表扫描的原因;
所以函数加在驱动表上不会触发全表扫描(指的是在条件中的字段加的函数,在select加的没影响)
 
4.连表查询字段类型不一致导致索引失效:
from work_order left join work_order_asset_details b
on work_order.id = b.work_order_id
1.伴随着Using join buffer (Block Nested Loop)一起出现
解决方式:连接条件上加上索引
2.work_order表是驱动表,其中id为整型,b表为被驱动表,触发了隐式类型转化
on cast(b.work_order_id as signed int) = work_order.id
由于函数作用在了被驱动表上,导致索引失效
 
tip1: 修改字段类型一致(推荐) alter table work_order_asset_details modify column work_order_id int(11) ;
tip2: 在驱动表上将其类型转化成和被驱动表上类型一致(治标不治本,临时方案)
on work_order.id = cast(b.work_order_id as char)
 
总结: 对索引字段做函数操作,可能会破坏索引值的有序性,因此优化器就决定放弃走树搜索功能。
 
5.连表的排序规则(utf8mb4_general_ci)不一致,不仅会导致索引失效,而且还会报错
 
mysql 连表分析:
前提:可以使用被驱动表的索引
I.使用join语句,性能比强行拆成多个单表执行SQL语句的性能要好;
II.如果使用join语句的话,需要让小表做驱动表。
 
判断使用join的先决条件:
t1(id index_a b ) ---在t1上有主键索引,a字段的索引 b上没有索引
t2(id index_a b) ---在t2上有主键索引,a字段的索引 b上没有索引
 
explain select * from t1 straight_join t2 on t1.a = t2.b
(straight_join------内左连接)
由于被驱动表t2的b字段上没有索引,可以在explain中extra中可以看到
“Block Nested Loop”字样 ------分块嵌套循环(由于被驱动表上没有用的上的索引导致的), 会导致扫描被驱动表很多次,占用大量的系统资源,所以这种join尽量不要用
 
如果是“Index Nested-Loop Join” ,表示用上了被驱动表的索引字段,是没问题的
当然应该选择小表做驱动表
 
如果是Block Nested-Loop Join算法,无法优化sql(无法加索引),可以使用以下方式
优化:
1.在join_buffer_size不够大的时候(这种情况更常见),应该选择小表做驱动表
2.在join_buffer_size足够大的时候,是一样的;
 
小结:在决定哪个表做驱动表的时候,应该是两个表按照各自的条件过滤,过滤完成之后,计算参与join的各个字段的总数据量,数据量小的那个表,就是“小表”,应该作为驱动表。
所以inner join自动选择驱动表并不是万能的,这时候分析sql后,使用straight_join的好处就凸显了
 
当查询的的条件和查询的结果都是索引中的字段的时候,这个索引我们可以称之为覆盖索引,这个时候,使用like模糊查询索引是有效的
 

发表评论

0/200
143 点赞
0 评论
收藏