- 是帮助mysql高效获取数据的数据结构(有序)。在数据之外,数据库系统还维护着满足特定查找算法的树结构,这些数据结构以某种方式引用(指向)数据,这样就可以在这些数据结构上实现高级查找算法,这种数据结构就是索引。
- (1)提高查询效率:提高数据检索的效率,降低数据库的IO成本。
- (2)提高排序效率:通过索引列对数据进行排序,降低数据排序的成本,降低CPU的消耗。
- (1)索引列占用空间;
- (2)降低更新表的速度,如对表进行insert、update、delete时,效率降低。
- (1)B+Tree索引:最常见的索引类型,大部分引擎都支持B+Tree索引。
- (2)hash索引:底层数据结构使用哈希表实现的,只有精确匹配索引列的查询才有效,不支持范围查询。
- (3)R-Tree索引:空间索引是MyIsam引擎的一个特殊索引类型,主要用于地理空间数据类型,通常使用较少。
- (4)Full-Text索引:是一种通过建立倒排索引,快速匹配文档的方式,类似于Lucene、Solr、ES。
- 特点:左侧比根节点的数值小,右侧比根节点的数值大。
- 缺点:
(1)顺序插入时,会形成一个链表,查询性能大大降低。
(2)二叉树一个节点下面,最多只能包含两个子节点;大数据情况下,层级较深,检索速度慢。
- 特点:自平衡的二叉树。
- 解决了二叉树顺序插入时,形成链表的缺点。
- 红黑树是自平衡的二叉树,所以也会存在,大数据情况下,层级较深,检索速度慢。
- 又称多路平衡查找树。
- 特点:
(1) 在根节点、叶子节点、非叶子节点下面都有数据。
(2)在进行分裂后,向上分裂的数据,在叶子节点不会存在。- 分裂演变地址:https://www.cs.usfca.edu/~galles/visualization/BTree.html
- 特点:
(1)非叶子节点只起到索引的作用,叶子节点用来存放数据。
(2)在进行分裂后,向上分裂的数据,在叶子节点也会存在。(所有的元素都会出现在叶子节点)
(3)叶子节点形成一个单向链表。- mysql索引数据结构对经典的B+Tree进行了优化。在原B+Tree的基础上,增加了一个指向相邻叶子节点的链表指针,就形成了带有顺序指针的B+Tree,提高区间访问的性能。(即双向链表)
- 分裂演变地址:https://www.cs.usfca.edu/~galles/visualization/BTree.html
- 哈希索引就是采用一定的hash算法,将键值换算成新的hash值,映射到对应的槽位上,然后存储在hash表中。
- 会出现哈希冲突,哈希冲突通过链表来解决,向链表追加元素即可。
- 特点:
(1)hash索引只能用于对等比较(=、in);不支持范围查询(between、>、<…);
(2)无法利用索引完成排序操作;
(3)查询效率高,通常只需要检索一次就可以了,效率通常高于B+Tree索引。
(1)相对于二叉树,层级更少,搜索效率高;
(2)对于BTree,无论是叶子节点爱是非叶子节点,都会保存数据,这样导致一页中存储的键值减少,指针跟着减少,要同样保存大量数据,只能增加树的高度,导致性能降低。
(3)相对于hash索引,B+Tree支持范围匹配及排序操作。
(4)B+Tree,只在叶子节点存放数据,搜索效率稳定;叶子节点形成双向链表结构,便于范围搜索和排序。
(一页是16K)
(1)如果存在主键,主键索引就是聚集索引;
(2)如果不存在主键,将使用第一个唯一索引作为聚集索引;
(3)如果表没有主键,或没有合适的唯一索引,则InnoDB会自动生成一个rowId作为隐藏的聚集索引。
- 先到二级索引中查找数据,找到主键值,然后再到聚集索引中根据主键值,获取数据的方式,称之为回表查询。
- 创建索引:
CREATE {UNIQUE | FULLTEXT} INDEX index_name ON table_name(index_col_name,…);- 查看索引:
SHOW INDEX FROM table_name;- 删除索引:
DROP INDEX index_name ON table_name;
#开启mysql慢查询日志开关
slow_query_log=1
#设置慢查询日志的时间为0.002秒,SQL语句执行时间超过0.002秒,就会视为慢查询,记录慢查询日志
long_query_time=0.002
- 根据如下例子,可以看出;使用索引进行查询的性能大大提升。
查询从索引的最左列开始,并且不跳过索引中的列。如果跳跃某一列,则后面的字段索引失效。
- 建立联合索引:idx_name_age_job
- 使用name、age、job进行查询:
- 使用name、age进行查询:
- 使用name、job进行查询:
- 使用age、job进行查询:
- EXPLAIN SELECT * FROM emp WHERE NAME = ‘金庸’ AND age > ‘66’ AND job = ‘总裁’
- EXPLAIN SELECT * FROM emp WHERE NAME = ‘金庸’ AND age >= ‘66’ AND job = ‘总裁’
- emp表中的索引如下:
(1)未对索引列进行运算操作,索引未失效
(2)对索引列进行运算操作,索引失效
(1)字符串类型的字段在使用时,加引号,索引未失效。
(2)字符串类型的字段在使用时,不加引号,索引失效。
(1)头部模糊匹配,索引失效
(2)尾部模糊匹配,索引不失效
(3)头尾部均模糊匹配,索引失效
- use index:建议mysql使用哪一个索引完成此次查询
- 语法:explain select 查询字段 from 表名 use index(索引名) where 条件;
- ignore index :忽略指定的索引
- 语法:explain select 查询字段 from 表名 ignore index(索引名) where 条件;
- force index:强制使用索引
- 语法:explain select 查询字段 from 表名 force index(索引名) where 条件;
- 现在emp表的索引情况:
(1)查询字段未超出联合索引范围,未进行回表查询
(2)查询字段未超出联合索引范围,未进行回表查询
(3)查询字段超出联合索引范围,进行了回表查询
(4)查询字段超出联合索引范围,进行了回表查询
- Using where; Using Index ------>查找使用了索引,但是需要的数据都在索引列中能找到,所以不需要回表查询数据。
- Using index condition ---------->查找使用了索引,但是需要回表查询数据。
当字段类型为字符串(varchar,text,longtext等)时,有时候需要索引很长的字符串,这会让索引变得很大,查询时,浪费大量的磁盘IO, 影响查询效率。此时可以只将字符串的一部分前缀,建立索引,这样可以大大节约索引空间,从而提高索引效率。
- create index 索引名 on 表名(column(阿拉伯数字)) ;
- 可以根据索引的选择性来决定,而选择性是指不重复的索引值(基数)和数据表的记录总数的比值,索引选择性越高则查询效率越高, 唯一索引的选择性是1,这是最好的索引选择性,性能也是最好的。
一个索引只包含单个列。
一个索引包含了多个列。
CREATE INDEX idx_name ON USER(NAME);
- 针对于数据量较大,且查询比较频繁的表建立索引;
- 针对于常作为查询条件(where)、排序(order by)、分组(group by)操作的字段建立索引;
- 尽量选择区分度高的列作为索引,尽量建立唯一索引,区分度越高,使用索引的效率越高;
- 如果是字符串类型的字段,字段的长度较长,可以针对于字段的特点,建立前缀索引;
- 尽量使用联合索引,减少单列索引,查询时,联合索引很多时候可以覆盖索引,节省存储空间,避免回表,提高查询效率;
- 要控制索引的数量,索引越多,维护索引结构的代价也就越大,会影响增删改的效率。
- 如果索引不能存储null值,在创建表时使用not null约束它。当优化器知道每列是否包含null值时,它可以更好的确定哪个索引最有效的用于查询。