---------------如果使用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. 索引覆盖查询时很快的。