您的位置:

浅谈mysql数据库索引应用(mysql数据库的索引有哪些)

本文目录一览:

mysql索引

二叉搜索树、N叉树

页分裂:B+树的插入可能会引起数据页的分裂,删除可能会引起数据页的合并,二者都是比较重的IO消耗,所以比较好的方式是顺序插入数据,这也是我们一般使用自增主键的原因之一。

页分裂逆过程:页合并,当删除数据后,相邻的两个数据页利用率很低的时候会做数据页合并

主键索引:key:主键,value:数据页,存储每行数据

非主键索引:key:非主键索引,value:主键key,导致回表

最左匹配:优先将区分度高的列放到前面,这样可以高效索引,

最左匹配原则遇到范围查询就停止匹配,范围查询(、、between、like)为什么?因为出现范围匹配后,后面的索引字段无法保证有序,局部有序失去,顺序失去则无法提高查询效率

SELECT * FROM table WHERE a IN (1,2,3) and b 1;

如何建立索引?

还是对(a,b)建立索引,因为IN在这里可以视为等值引用,不会中止索引匹配,所以还是(a,b)!

索引组织表

索引用页存储:key【10】-point【6】,通过调整key大小,当页大小固定的情况下,通过调整key大小,使得N叉树变化;

如key 10, point 6则单个索引16字节,页大小为16k,则页面总共可以存储1024个索引,即N大小

覆盖索引: 二级索引的信息已经存在想要的列,例如主键

如果现在有一个高频请求,要根据市民的身份证号查询他的姓名,这个联合索引就有意义了。它可以在这个高频请求上用到覆盖索引,不再需要回表查整行记录,减少语句的执行时间。

索引下推优化:可以在索引遍历过程中,对索引中包含的字段先做判断,直接过滤掉不满足条件的记录,减少回表次数。

整理索引碎片,重建表:alter table T engine=InnoDB

  首先是看key的大小,另外是数据页的大小,如果需要改变N,则需要从这两个方面做改动;

一个innoDB引擎的表,数据量非常大,根据二级索引搜索会比主键搜索快,文章阐述的原因是主键索引和数据行在一起,非常大搜索慢,我的疑惑是:通过普通索引找到主键ID后,同样要跑一边主键索引,对于使用覆盖索引的情况下,使用覆盖索引可以直接解决问题

如何理解并正确使用MySql索引

MySQL索引类型包括:

(1)普通索引

这是最基本的索引,它没有任何限制。它有以下几种创建方式:

◆创建索引

CREATE INDEX indexName ON mytable(username(length)); 如果是CHAR,VARCHAR类型,length可以小于字段实际长度;如果是BLOB和TEXT类型,必须指定 length,下同。

◆修改表结构

ALTER mytable ADD INDEX [indexName] ON (username(length))

◆创建表的时候直接指定

CREATE TABLE mytable( ID INT NOT NULL, username VARCHAR(16) NOT NULL, INDEX [indexName] (username(length)) ); 删除索引的语法:

DROP INDEX [indexName] ON mytable;

(2)唯一索引

与前面的普通索引类似,不同的就是:索引列的值必须唯一,但允许有空值。如果是组合索引,则列值的组合必须唯一。它有以下几种创建方式:

◆创建索引

CREATE UNIQUE INDEX indexName ON mytable(username(length))

◆修改表结构

ALTER mytable ADD UNIQUE [indexName] ON (username(length))

如何高效地利用MySQL索引

1、要想高效利用索引,我们首先要考虑如何正确建立索引。

(1)在经常做搜索的列上,也就是WHERE子句里经常出现的列,考虑加上索引,加快搜索速度。

(2)唯一标识记录的列,应该加上唯一索引,强制该列的唯一性并且加快按该列查找记录的速度。

(3)在内连接使用的列上加上索引,最好是在内连接用到字段都加上,因为MySQL优化器会自动地选择连接顺序,然后观察索引的使用情况,将没用的索引删除即可。

(4)在需要排序的列上加上索引,因为索引本身是按顺序的组织的,它可以避免 filesort,要知道,Server层在进行排序时是在内存中进行的,非常消耗资源。

(5)可以考虑实现覆盖索引,即根据 SELECT 的所有字段上创建联合索引,这样存储引擎只用读取索引而不用去回表查询,极大地减少了对数据表的访问,大大地提高了性能。

(6)对于那些选择性很小的列,比如性别列,增加索引并不能明显加快查询速度,反而该索引会成为表的累赘。

(7)对于那些定义为text, image和bit数据类型的列不应该增加索引。这是因为,这些列的要么数据量相当大,要么取值很少。

(8)当对写性能的要求远远大于读性能时,不应该创建索引。写性能和读性能是互相矛盾的。这是因为,维护一个 B+Tree 成本是非常大的,对索引的写会涉及到页的分裂等。

(9)复合索引的几个字段是否经常同时以AND方式出现在Where子句中?单字段查询是否极少甚至没有?如果是,则可以建立复合索引,否则考虑单字段索引。这还是说明,满足查询性能的前提下,索引越少越好。

(10)如果复合索引所包含的字段超过3个,那么仔细考虑其必要性,考虑减少复合的字段。

(11)在用于GROUP BY的列上加上索引,避免使用临时表。

(12)对于较长的字符列,如 char、varchar等,由于字符串的比较相对来说非常耗时,因此考虑使用前缀索引减少索引长度,或者创建自定义哈希索引,将字符串映射成整数,然后以该整数作为索引,同时以字符串的值作为过滤条件。

我们在创建索引时,可以根据下面原则进行简单判断:索引是否将相关记录集合到了一起,从未减少了磁盘I/O,加快搜索速度?索引中数据的排列顺序是否和查找的数据的排列顺序一致,从而避免了Server层的排序?索引中的列是否包含了查询中需要的全部列从而实现了覆盖索引? 这几个条件层层递进,满足得越多越好。

2、索引正确地建立了,我们还需要正确地使用它们:

(1)使用了运算符 !=,以及关键字not in,not exist,,等,总之产生的结果集很大时(也在where条件进行大范围的选择时),往往导致引擎不使用索引而是走全盘扫描。因为如果使用索引会造成大量的随机I/O,得不偿失。

(2)如果对索引列进行运算,如 WHERE substr(name, 1, 3)=‘mark’,存储引擎并不能聪明地判断哪些索引满足等式,因此不能使用到索引。

(3)使用到了LIKE,并且通配符在最前面时,不能使用索引。

(4)对于联合索引 (a, b, c),如果没用到最左列,那么一般情况下都使用不到索引。但是,比如统计操作 count(*) where a xxx,是可以使用到该联合索引的。毕竟统计这类操作,它不是检索,并不需要索引完全有序。

(5)对于联合索引,如果某个列使用了范围查找,那么其右边的列都无法作为索引优化查询,但是由于 ICP(Index Condition Pushdown),这些列能作为过滤条件在存储引擎中对数据进行过滤。

(6)如果条件中有 OR,则必须每个OR用到的字段都有索引,否则不能使用任何索引。

(7)想在联合查询中使用索引来避免 filesort,则关联查询中的ORDER BY用到的字段必须全部是第一张表(驱动表)上的。

深入浅析Mysql联合索引最左匹配原则

之前在网上看到过很多关于mysql联合索引最左前缀匹配的文章,自以为就了解了其原理,最近面试时和面试官交流,发现遗漏了些东西,这里自己整理一下这方面的内容。

最左前缀匹配原则

在mysql建立联合索引时会遵循最左前缀匹配的原则,即最左优先,在检索数据时从联合索引的最左边开始匹配,示例:

对列col1、列col2和列col3建一个联合索引

KEY test_col1_col2_col3 on test(col1,col2,col3);

联合索引 test_col1_col2_col3 实际建立了 (col1)、(col1,col2)、(col,col2,col3) 三个索引。

SELECT * FROM test WHERE col1=“1” AND clo2=“2” AND clo4=“4”

上面这个查询语句执行时会依照最左前缀匹配原则,检索时会使用索引(col1,col2)进行数据匹配。

注意

索引的字段可以是任意顺序的,如:

SELECT * FROM test WHERE col1=“1” AND clo2=“2”

SELECT * FROM test WHERE col2=“2” AND clo1=“1”

这两个查询语句都会用到索引(col1,col2),mysql创建联合索引的规则是首先会对联合合索引的最左边的,也就是第一个字段col1的数据进行排序,在第一个字段的排序基础上,然后再对后面第二个字段col2进行排序。其实就相当于实现了类似 order by col1 col2这样一种排序规则。

有人会疑惑第二个查询语句不符合最左前缀匹配:首先可以肯定是两个查询语句都保函索引(col1,col2)中的col1、col2两个字段,只是顺序不一样,查询条件一样,最后所查询的结果肯定是一样的。既然结果是一样的,到底以何种顺序的查询方式最好呢?此时我们可以借助mysql查询优化器explain,explain会纠正sql语句该以什么样的顺序执行效率最高,最后才生成真正的执行计划。

减少开销 。建一个联合索引(col1,col2,col3),实际相当于建了(col1),(col1,col2),(col1,col2,col3)三个索引。每多一个索引,都会增加写操作的开销和磁盘空间的开销。对于大量数据的表,使用联合索引会大大的减少开销!

覆盖索引 。对联合索引(col1,col2,col3),如果有如下的sql: select col1,col2,col3 from test where col1=1 and col2=2。那么MySQL可以直接通过遍历索引取得数据,而无需回表,这减少了很多的随机io操作。减少io操作,特别的随机io其实是dba主要的优化策略。所以,在真正的实际应用中,覆盖索引是主要的提升性能的优化手段之一。

效率高 。索引列越多,通过索引筛选出的数据越少。有1000W条数据的表,有如下sql:select from table where col1=1 and col2=2 and col3=3,假设假设每个条件可以筛选出10%的数据,如果只有单值索引,那么通过该索引能筛选出1000W10%=100w条数据,然后再回表从100w条数据中找到符合col2=2 and col3= 3的数据,然后再排序,再分页;如果是联合索引,通过索引筛选出1000w10% 10% *10%=1w,效率提升可想而知!

引申

对于联合索引(col1,col2,col3),查询语句 SELECT * FROM test WHERE col2=2; 是否能够触发索引?

大多数人都会说NO,实际上却是YES。

原因:

EXPLAIN SELECT * FROM test WHERE col2=2;

EXPLAIN SELECT * FROM test WHERE col1=1;

观察上述两个explain结果中的type字段。查询中分别是:

index: 这种类型表示mysql会对整个该索引进行扫描。要想用到这种类型的索引,对这个索引并无特别要求,只要是索引,或者某个联合索引的一部分,mysql都可能会采用index类型的方式扫描。但是呢,缺点是效率不高,mysql会从索引中的第一个数据一个个的查找到最后一个数据,直到找到符合判断条件的某个索引。所以,上述语句会触发索引。

ref: 这种类型表示mysql会根据特定的算法快速查找到某个符合条件的索引,而不是会对索引中每一个数据都进行一一的扫描判断,也就是所谓你平常理解的使用索引查询会更快的取出数据。而要想实现这种查找,索引却是有要求的,要实现这种能快速查找的算法,索引就要满足特定的数据结构。简单说,也就是索引字段的数据必须是有序的,才能实现这种类型的查找,才能利用到索引。

以上所述是我给大家介绍的Mysql联合索引最左匹配原则,希望对大家有所帮助,如果大家有任何疑问请给我留言,我会及时回复大家的。

《 两个月拿到N个offer,看看我是如何做到的 》

《 面试总结:2019年最全面试题资料学习大全—(含答案) 》

《 淘宝面试回来,想对程序员们谈谈 》

《 看过太多大厂面试题,其实考的无非是这 3 点能力 》

MySQL数据库优化(七):MySQL如何使用索引

索引用于快速找到特定一些值的记录。如果没有索引,MySQL就必须从第一行记录开始读取整个表来检索记录。表越大,资源消耗越大。如果在字段上有索引的话,MySQL就能很快决定该从数据文件的哪个位置开始搜索记录,而无须查找所有的数据。如果表中有1000条记录的话,那么这至少比顺序地读取数据快100倍。注意,如果需要存取几乎全部1000条记录的话,那么顺序读取就更快了,因为这样会使磁盘搜索最少。

大部分MySQL索引(PRIMARY KEY, UNIQUE,INDEX 和 FULLTEXT)都是以B树方式存储。只有空间类型的字段使用R树存储,MEMORY (HEAP)表支持哈希索引。

字符串默认都是自动压缩前缀和后缀中的空格。

通常,如下所述几种情况下可以使用索引。哈希索引(用于 MEMORY 表)的独特之处在后面会讨论到。

想要尽快找到匹配 WHERE 子句的记录。

根据条件排除记录。如果有多个索引可共选择的话,MySQL通常选择能找到最少记录的那个索引。

做表连接查询时从其他表中检索记录。

想要在指定的索引字段 key_col 上找到它的 MIN() 或 MAX() 值。优化程序会在检查索引的

key_col 字段前就先检查其他索引部分是否使用了 WHERE key_part_# = constant 子句。这样的话,

MySQL会为 MIN() 或 MAX() 表达式分别单独做一次索引查找,并且将它替换成常数。当所有的表达式都被替换成常数后,查询就立刻返回。如下:

SELECT MIN(key_part2),MAX(key_part2) FROM tbl_name WHERE key_part1=10;

对表作排序或分组,当在一个可用的最左前缀索引上做分组或排序时(如 ORDER

BY key_part1, key_part2)。如果所有的索引部分都按照 DESC 排序,索引就按倒序排序。

有些时候,查询可以优化使得无需计算数据就能直接取得结果。当查询使用表中的一个数字型字段,且这个字段是索引的最左部分,则可能从索引树中能很快就取得结果:

SELECTkey_part3FROMtbl_nameWHEREkey_part1=1

假设有如下 SELECT 语句:

如果在 col1 和 col2 上有一个多字段索引的话,就能直接取得对应的记录了。

MySQL索引

MySQL的Innodb存储引擎的索引分为聚集索引和非聚集索引两大类

特点:B+树叶子节点存储行数据

一个表中,必须有一个聚集索引,只能有一个聚集索引,Innodb通常把一个表的主键索引作为聚集索引,如果没有主键InnoDB会选择一个唯一索引代替。如果没有这样的索引,InnoDB会隐式的定义一个主键来作为聚集索引,这个字段为6个字节,类型为长整形。

利用主键索引查找行数据是最快的,建议使用自增主键原因是利于索引树的构建(主键自增写入时新插入的数据不会影响到原有页,插入效率高;但是如果主键是无序的或者随机的,那每次的插入可能会导致原有页频繁的分裂,影响插入效率)

特点:B+树叶子节点存储主键ID

一个表中可以有多个非聚集索引,每个非聚集索引即是一棵B+树

通过非聚集索引查找数据时,需要先在非聚集索引上找到主键ID,再从聚集索引获取行数据,这个过程就称之为回表

B树索引中的B树实际上是B+树,至于为什么使用B+树而不使用B树或者红黑树的原因在另外的文章中有提及。

特点:

特点:类似JDK中的HashMap,但无法支持范围查询

特点:使用的算法仍然是B树索引,不同的就是索引列的值必须唯一

对于普通索引来说,查找到满足条件的第一个记录后,需要查找下一个记录,直到碰到第一个不满足条件的记录。

对于唯一索引来说,由于索引定义了唯一性,查找到第一个满足条件的记录后,就会停止继续检索,提升索引性能

另外插入行时会构建该唯一索引,假如索引值重复将插入失败,适合业务上做唯一性检验

通过建立倒排索引,可以极大的提升检索效率,解决判断字段是否包含的问题,但是业务上一般都不采用这种索引,而是使用ES处理全文搜索需求

仅对某个特定字段建立的索引,如(biz_id)

对多个字段建立的索引,如(biz_id,type)