mysql数据库索引的一些学习


在项目编写的过程中,遇到了一些数据库查询优化的问题,所以找了一些关于索引的书看。
现在把看完后的一些对数据库索引的理解整理一下,算是对自己学习的回顾,同时可能对数据库索引的理解有错误的,写出来了的话,如果有大佬能指出了就更好了。
文章写的初衷就是这样,希望以后能写更多。
看的一些关于mysql的,感觉比较好的书: 《高性能mysql(第三版)》《MySQL技术内幕》


1.mysql数据库存储方式和索引的关系
2.索引的几个基本索引类型
3.三星索引
4.查询优化的几种建议


mysql数据库存储方式和索引的关系

先简单说说mysql物理存储的方式吧。mysql数据库常用的存储引擎有2种。
1.myisam(不支持事务)
  myisam物理存储分为.frm文件,.myd文件,.myi文件.
  .frm文件: 存放和表相关的元数据信息,包括表结构的定义信息等等。各种存储引擎都需要frm文件,并且存放于数据库名目录下面。
  .myd文件:myisam存储引擎专用,用于存储myisam表的数据
  .myi文件:myisam存储引擎专用,用于存储myisam表的索引相关信息
2.innodb(支持事务,当前用作插件来安装)
  .frm文件
  .ibd文件:独享表存储方式使用的数据存储文件
  .ibdata文件:共享表空间存储方式使用的数据存储文件,所有的表共用一个ibdata文件。

mysql数据存储本质还是存储到文件里的。下面来说一说我们看到的数据库表的展示逻辑。
我们在新建表的时候,都是要指定一个唯一主键的,这个特殊的主键就是聚集索引。MySQL通过创建表的时候指定的聚集索引,把原本无序存放的数据,整理成了一个b树或者b+树类型的数据格式。它根据你绑定的索引的hash值进行排序,即key值是索引建立的具体数据的hash值,最后的叶子节点会指向真正的数据存储的地址,即value是具体查询的一整行数据的存放指针地址。
所以,如果你建立了索引,查询sql的时候,会判断到查询sql是否命中了b树中的key,如果命中了,会直接取到key值绑定的value,即行数据存放地址,这样查询的效率就会提高很多。


索引的几个基本索引类型

mysql中索引有很多种。但是比较常见的基本是4种。FULLTEXT,HASH,BTREE,RTREE。

  1. FULLTEXT
      即为全文索引,目前只有MyISAM引擎支持。其可以在CREATE TABLE ,ALTER TABLE ,CREATE INDEX 使用,不过目前只有 CHAR、VARCHAR ,TEXT 列上可以创建全文索引。
      全文索引并不是和MyISAM一起诞生的,它的出现是为了解决WHERE name LIKE “%word%"这类针对文本的模糊查询效率较低的问题。

  2. HASH
      由于HASH的唯一(几乎100%的唯一)及类似键值对的形式,很适合作为索引。
      HASH索引可以一次定位,不需要像树形索引那样逐层查找,因此具有极高的效率。但是,这种高效是有条件的,即只在“=”和“in”条件下高效,对于范围查询、排序及组合索引仍然效率不高。

  3. BTREE
      BTREE索引就是一种将索引值按一定的算法,存入一个树形的数据结构中(二叉树),每次查询都是从树的入口root开始,依次遍历node,获取leaf。这是MySQL里默认和最常用的索引类型。

  4. RTREE
      RTREE在MySQL很少使用,仅支持geometry数据类型,支持该类型的存储引擎只有MyISAM、BDb、InnoDb、NDb、Archive几种。

上面4种索引类型的介绍是我百度的。这些了解一下就可以。我们主要说说我们常用的 hash和b_tree索引。
(一个好的博客传送门https://www.cnblogs.com/xiaoboluo768/p/5164342.html)
1.hash
  1.1 hash索引是key_value结构。可以快速定位到查询的数据。
  1.2 hash仅仅满足 =,in,<=> 结构的sql索引,不能使用范围查询。
  1.3 hash不能使用排序的索引,仅仅适合无序的SQL查询
  1.4 hash不能用于部分索引的命中。比如索引建立的是 (a,b,c)的组合索引,如果你sql里写的是
     select xx from XX where a = xx and b = xx; 那么这个组合索引就没有效果了。你的where语句里必须要把 where     a = xx and b = xx and c =xx写全才有用。
  1.5 hash不能避免全表的扫描。hash值计算可能是相同的,如果相同的hash值很多,就可能会多次查表。

2.b-tree
(对b-tree原理的一个很好的解答的博客网址 https://blog.csdn.net/u013235478/article/details/50625677)
  2.1 b-tree索引是有顺序的,可以使用 =,>, >=,<,<=,betwwen。如果使用like的话,不以通配符%开头是可以使
   用索引的。比如
   select k from a where a.b like 'm%';
    这个时候是可以使用索引a.b的。但是下面这种就不能了;
   select k from a where a.b like '%m%';
  2.2 b-tree索引可以使用部分索引,比如 索引 a,b,c 这个时候 索引成立条件有 where (a,b,c),(a,b),(a)。
    ps:新的MySQL a,c,b 这种错序的也可以用b-tree索引了。
这里随意说说,添加了索引之后,为什么对数据更新和添加有影响。因为索引建立是一个树状的,如果数据改变了,索引的树就要重新排序,同时如果数据库存储的叶子页容量不够,是要自动分裂的,这种分裂可能造成空白容量的浪费。


三星索引

三星索引就是一个评判你索引建立的好坏的一个标准(传送门:https://blog.csdn.net/fly43108622/article/details/80731849)
1.把查找的值的建写在select语句里。比如 索引是a,你查找的也是a,那么select a from xxx 这个就是1星。不要写 select * from a xxx 这个样子 索引要去取key值里指定的value对应的具体的数据,如果写 select a的话,索引就不会根据地址取具体的数据,而是直接取key。
2.把 =这些非范围查找的放在where开头,比如 where a = x and b like '%c%' 不要写成 where b like '%c%' and a = x;索引遇到这种范围查找就会部分失效。同时索引的顺序要和 where中一致。比如 索引 a,b,c where语句中 也要是 a,b,c的顺序。 2星
3.把排序的语句也按序建立索引。比如 orderby语句 也要建立索引 3星。
这里有个小小主意点 。就是建立索引的时候,把最能减小数据量的列放在索引的第一位,这样的索引才是最快的。


查询优化的几个建议

1.避免在where语句中使用 is null is not null这种。索引会无效
2.对于 in not in 尽量用 between. exits
3.不要用 or (当然看 你实际情况了)
4.不要用使用函数和表达式 比如 where a = (b+1) 索引遇到函数会无效。
5.不要用 select *
6.避免频繁更新的列成为索引
7.每个表的索引数量不用过多
8.写对where的类型 比如 where a = 1000;但是 a的类型是 varchar 就写成 where a = '1000'。

暂时先写这么多。比较浅陋。 希望有人指正。

你可能感兴趣的:(mysql数据库索引的一些学习)