mysql索引优化使用

   工作一直也没有把自己学到跟看到的一些东西记录下来,有些学到的东西很久没遇到,自己也有些模糊了。从今天开始记录一下,自己记录一遍是对自己的巩固,也是一种分享,虽然可能对于一些人来说分享的内容很浅,但也可能会帮助另一些人。

  工作中有的时候一条sql很慢,这时候就就会进行sql的优化,sql优化有多方面,对sql进行优化,对sql添加索引等,但是sql的索引应该怎么加,又应该怎么用,加的索引有没有真正发挥完全等。索引主要作用是告诉存储引擎怎么样快速找到存储数据,MySQL常用的索引方法有b-tree,hash。b-tree索引的特点,他是以b+tree的结构存储数据,每一个叶子节点都包含指向下一个叶子节点的指针,可以方便的进行叶子节点的遍历,简单的画个图:

  

  从图中很明显的可以看出每次查询的时候需要扫描的列会比全表扫面少很多,所以会大大提高查询效率。当然对于b+treeMySQL的不用引擎对它实现方法是不一样的,对于InnoDB引擎叶子节点指向的是被索引列的主键,而MyISAM指向的则是物理位置,在查询语句下MySQL的第一次io将从根节点搜索找到叶子节点,MySQL的InnoDB引擎存储数据文件打大小默认为16k,每次子节点向下最终找到数据存储的位置,将文件io读取到内存中,再将需要查找的数据进行比较,这样就减少MySQL每次的io次数,大大的提高数据检索效率。另外btree索引很适合范围区间查找,所有的叶子结点和相连的节点使用链表相连,便于区间查找和遍历,而不需要回到父节点。

  btree索引使用不生效的几种情况:

  表结构

  

  添加的索引列

  

  

  

  

  

  上面的查询并没有使用索引,进行了全表扫描,我们修改一下发现使用了索引,原因是因为store_mobile字段类型是varchar类型,查询如果不使用字符串将不走索引

  

  

  我们发现查询都没有使用索引,当我们使用了not in关键字之后,将不走索引

  

  

  在查询结果为空的情况下将不走索引

  

  

  

  

  

  

  三次like查询发现前两次没有走索引,只有‘%’在最右边查询才会走索引

  

  

  

  

  两次查询发现使用is not null 查询将不走走索引,而is null 查询可以走索引

  

  

  查询如果使用or,并且store_name字段没有加索引的时候,我们发现查询并没有走索引,我们来验证到底是or影响了查询还是store_mobile字段没有加索引应行了查询

  我们创建一个组合索引(我们多加一个列因为下面要测试另一个东西)

  

  

  

  通过第二次查询发现是or的原因使查询没有走索引

  

  

  

  

  

  

  

  

  我们发现几次的查询只有store_mobile字段在查询条件最前面才会走索引,如果查询条件按没有store_mobile将不会走索引,这就是索引的最佳左匹配原则

  这种联合索引我么应该入选选择索引的顺序呢

  1.首先我们应该根据我们自己的业务场景,经常使用的列优先,但这并不是绝对的列出平常查询的类型或者性别的列,选择性很小,MySQL也不见得一定会使用索引,可能查询优化却觉得全表扫描的效率更高,这也就引入了第二种情况

  2.选择性高的的优先,这样完成对最左边列的筛选后,后面需要筛选的列就变少了

  3.宽度小的列优先,这样MySQL每页存储的索引就会越多,io的次数越少,当然在不违反选择性高的前提下

  btree索引简单介绍这么多,另外还有一中索引叫hash索引,hash索引本质是为每一行计算了一个hash码,索引中存储的就是hash码,所以hash索引只有在进行等值查询的情况下才能使用索引,进行范围差找跟模糊差找都不能使用hash索引,hash索引不像btree是有顺序的存储,所以hash索引无法用于排序,hash索引本身会为行计算hash值,所以会产生hash冲突,在对于选择性比较差的列,例如性别,只有男跟女,这样就不适合使用hash索引,像身份证存储的是18为数字,这样的简历hash索引就比较合适。

  使用索引跟不使用索引的对锁的数据也不一样

  首先我们先给查询加一个锁

  begin;
  select * from store where id =1 for update;

  然后的开另一个窗口执行

  update store set store_name='测试1' where id=1 ;

  发现这条语句一直在执行,然后我们打开另一个链接窗口

  update store set store_name='测试2' where id=2;

  发现立马执行完,然后我们在第一个窗口输入

  commit;

  发现第二个窗口的sql立马执行完,说明对有索引的列进行搜索的时候,锁的是这一行的数据

  我们继续测试,执行

  begin;
  select * from store where store_name='测试1' for update;

  打开另一个窗口执行

  update store set store_name='测试3' where id=3;

  sql还在执行,我们回到第一个窗口执行

  commit;

  发现立马执行完毕,这时候发现在对没有索引列进行查询的时候,锁的是整个表的数据

   这篇文章简单的介绍了一下索引,下一篇文章将继续分享sql优化,文章会有很多不足,欢迎大佬吐槽

原文地址:https://www.cnblogs.com/HuuuWnnn/p/11139308.html