Mysql创建高性能的索引

 ---------------如果使用ORM框架,是否还需要关心索引-------------

是的,即使使用ORM工具。因为ORM工具通常只能在针对主键查询的时候,生产合法,符合逻辑的查询语句。否则很难生成合适的查询。无论多么复杂的ORM工具,在精妙和复杂的索引面前都是“浮云”。

InnoDB的索引和MyiSAM的区别(https://www.cnblogs.com/olinux/p/5217186.html)

索引的优点:

          1.     索引大大减少了服务器需要扫描的数据量

          2.    索引可以帮助服务器避免排序和临时表。

          3.    索引可以将随机IO变为顺序IO。 

1.     索引的类型:

 1.1.     B-Tree索引

(具体的B-Tree和B+Tree的区别https://blog.csdn.net/pangchengyong0724/article/details/76168576)

实际上很多存储引擎使用的是B+Tree,即每一个叶子节点都包含指向下一个叶子节点的指针,从而方便叶子节点的范围遍历。通常B-Tree索引意味着所有的值都是按顺序存储的,并且每一个叶子页到根的距离相同。

InnoDB下,B-Tree索引能够提升访问数据的速度,因为存储引擎不再需要进行全表扫描,只需要从索引的根节点开始搜索。根节点的槽中存放了指向子节点的指针,存储引擎可以根据这些指针向下查找,然后通过比较值来获取数据。

叶子结点比较特殊,他们的指针指向的是被索引的数据,而不是其他叶子节点。

                   索引对多个值进行排序的依据就是create table语句中定义索引时的顺序。


 适合使用B-Tree的查询类型:

                   B-Tree索引适用于全键值、键值范围或键前缀查找。其中键前缀只适合用于根据最左前缀查找(MySQL相关特性)。如:(A,B,C)

              全值匹配:

                                指的是和索引中所有的列进行匹配。A and B and C

              匹配最左前缀:

                                 索引的第一列:如A=...

              匹配列前缀:

可以用于查找所有以第一列开头的模糊匹配,比如A%,只是用了第一列。

              匹配范围值:

                                  可以匹配第一列的范围值,比如从Allen和Barrymore之间的人。只是用了第一列。

              精确匹配某一列并范围另外一列:

                                  比如 A and B%

              只访问索引的查询:     

                                  只访问索引,无需访问数据行。

因为索引树中的节点是有序的,所以除了按值查找意外,索引还可以用于查询中的ORDER BY操作(按顺序查找)。所以ORDER BY字句满足前面列出的几种查询类型,则这个索引也可以满足对应的排序需求


              B-Tree索引的限制:

                   1.     如果不是按照索引的最左列开始查找,则无法使用索引。

                   2.     不能跳过索引中的列。比如A and C ,这样只能使用第一列A索引。

                   3.     如果查询中有某个列的范围值,则其右边的所有列无法使用索引优化查找。

  1.2         哈希索引

 哈希索引基于哈希表实现的,只有精确匹配索引所有列的查询才有效。对于每一行数据,存储引擎会对所有的索引列计算一个哈希码。存储在索引中,同时哈希表中保存指向每个数据的指针。MySQL中,只有Memory引擎支持哈希索引。


              哈希索引的限制:

                        1.     哈希索引只包含哈希值和行指针,而不存储字段值,索引不能使用索引中的值来避免读取行。

                        2.     不是按顺序的,所以不能排序。

                        3.     哈希索引也不支持部分索引列匹配查找。如,在(A,B)上建立索引,查询只有列A,无法使用索引。

                        4.     哈希索引只支持比较查询,包括=、IN()、<=>(<>和<=>是不同的操作),也不支持范围查找,如:where price > 100;

                        5.     访问哈希表的速度很快,除非有哈希冲突。


         InnoDB引擎有一个特殊的功能叫做 “自适应哈希索引”。当InnoDB注意到某些索引值被使用的很频繁时,他会在内存中基于B-Tree索引之上在建立一个哈希索引,这就让B-Tree索引也具有了哈希索引的有点,比如快速查找,这是一个完全自动的,内部行为,用户无法控制。




 1.3            空间数据索引 

 MyISAM支持空间索引,可以用做地理数据存储,和B-Tree索引不同,查询时支持任何维度来组合查询。必须使用MySQL的GIS函数如MBRCONTAINS()等来维护数据。但是开源数据库系统对GIS的解决方案做的比较好的是PostgreSQL的PostGIS。       

1.4           全文索引

 全文索引是一种特殊的索引,他不是比较值而是查找文本中的关键词,有许多需要注意的细节,比如停用词,词干和复数,布尔搜索等等。更类似于搜索引擎,不是简单的where语句匹配。 

                   

                 可以再相同的列上同时建立全文索引和基于值的B-Tree索引,不会起冲突,全文搜索适用于Match aganist操作,而不是普通的where条件操作。

 索引的使用注意:

 独立的列:

              如果查询中的列不是独立的,则MySQL就不会使用索引。“独立的列”是指索引列不能是表达式的一部分,也不能是函数的参数。比如;     select actor_id from sakila.actor where actor_id + 1 = 5;

 前缀索引和索引的选择性:

              有时候需要索引很长的字符串,这会使索引变得大且慢,一种办法就是模拟哈希索引,通常还可以索引开始的部分字符,这样可以大大节约索引空间,从而提高索引效率。但是也会降低索引的选择性。索引的选择性是指,不重复的索引值(也称为基数)和数据表的记录总数(#T)的比值,范围从1/#T 到 1之间。选择性越高越好,因为选择性高的索引可以让MySQL在查找时过滤掉更多的行,选择行是1的时候,是最好的索引选择性,性能也是最好的

 使前缀的选择性接近于完整列的选择性。

              select count(distinct city)/count(*) from sakila.city_demo.

              创建前缀索引:

              alter table  sakila.city_demo  add key(city(7));

前缀索引无法使用order by 和 group by。

 多列索引:

              在多个列上建立独立的单列索引大部分情况下并不能提高MySQL的查询性能。MySQL5.0和更新版本引入了一种叫“索引合并”的策略。

              select film_id, actor_id from sakila.film_actor where actor_id = 1 or film_id =1;在老的MySQL版本中,MySQL对这个查询会使用全表扫描。除非改写成UNION的方式:

select film_id, actor_id from sakila.film_actor where actor_id = 1

              UNION ALL

select film_id, actor_id from sakila.film_actor where film_id = 1 and actor_id <> 1;


             MySQL5.0和更新的版本中,查询能够同时使用这两个单列索引进行扫描,并将结果合并。


当服务器需要对多个索引做联合操作时(通常有多个OR条件),通常需要耗费大量CPU和内存资源在算法的缓存,排序和合并上。特别是当有些索引的选择性不高,需要合并扫描返回大量数据的时候。

    

    选则合适的索引顺序:

 适用于B-Tree索引。对于如何选择列的顺序有一个经验法则:将选择性最高的列放到索引最前列。但是如果索引的选择性太低,再好的索引也很难起到作用。尽可能的将范围查询的列放到索引的后面,以便优化器使用更多的索引列。

总结:

          1.     单行数据访问是很慢的。特别是在机械硬盘存储中,使用索引创建位置引用以提升效率。

             2.    按顺序访问范围数据是很快的。第一,顺序IO不需要多次磁盘寻道,所以比随机IO要快很多。第二,如果服务器能够按照顺序读取数据,就不需要额外的排序操作。

             3.     索引覆盖查询时很快的。

你可能感兴趣的:(Mysql创建高性能的索引)