数据库的索引可以加快查询速度,原因是索引使用特定的数据结构(B-Tree)对特定的列额外组织存放,加快存储引擎(索引是存储引擎实现)查找记录的速度。
索引优化是数据库优化的最重要手段。

如果查询语句使用索引(通常是where条件匹配索引)就会利用树的结构加快查找,索引会按值查找到要查找的行在表中位置,不需回表查询数据的就是聚簇索引(索引和数据存放在一起)。通常是需要回表再查数据,需要消耗额外的磁盘IO。所以有些时候(如按顺序读取数据)全表扫描会比使用索引快的原因就在于此。

查询条件只有一个字段时,在该字段建立索引即可,可优化的地方是对于text blob字段使用前缀索引。

当查询条件有多个字段时,单列索引和多列索引有很大的区别。如果使用多列索引,where条件中字段的顺序非常重要,需要满足最左前缀列。最左前缀:查询条件中的所有字段需要从左边起按顺序出现在多列索引中,查询条件的字段数要小于等于多列索引的字段数,中间字段不能存在范围查询的字段(<,like等),这样的sql可以使用该多列索引。

二、多列索引适合的场景

1.全字段匹配

2.匹配部分最左前缀

3.匹配第一列

4.匹配第一列范围查询(可用用like a%,但不能使用like %b)

5.精确匹配某一列和和范围匹配另外一列

order by操作中出现的字段同样适用于按值查找的规则,where+order by中出现的字段需可以建立满足如上五种规则多列索引。 使用多列所需需要按照最左索引列查找;不能跳过中间列;如果某一列是范围查询,那么其右边所有列无法使用索引。 IN什么情况下是范围查询,什么情况下是多个等值查询?如果有order by排序时,多个等于条件查询就是范围查询,没有order by排序就没有限制。

例如,建立多列索引(name, age, id), 只能使用索引的前两列。in是范围查询
... where name='nginx.cn' and age in(15,16,17) order by id

可以使用整个索引,in是按值查询
... where name='nginx.cn' and age in(15,16,17) and id ='3'

三、复合索引的建立以及最左前缀原则

索引字符串值的前缀(prefixe)。如果你需要索引一个字符串数据列,那么最好在任何适当的情况下都应该指定前缀长度。
例如,如果有CHAR(200)数据列,如果前面10个或20个字符都不同,就不要索引整个数据列。索引前面10个或20个字符会节省大量的空间。你可以索引CHAR、VARCHAR、BINARY、VARBINARY、BLOB和TEXT数据列的前缀。
假设你在表的state、city和zip数据列上建立了复合索引。索引中的数据行按照state/city/zip次序排列,因此它们也会自动地按照state/city和state次序排列。这意味着,即使你在查询中只指定了state值,或者指定state和city值,MySQL也可以使用这个索引。因此,这个索引可以被用于搜索如下所示的数据列组合:
state, city, zip
state, city
state
MySQL不能利用这个索引来搜索没有包含在最左前缀的内容。例如,如果你按照city或zip来搜索,就不会使用到这个索引。如果你搜索给定的state和具体的ZIP代码(索引的1和3列),该索引也是不能用于这种组合值的,尽管MySQL可以利用索引来查找匹配的state从而缩小搜索的范围。
如果你考虑给已经索引过的表添加索引,那么就要考虑你将增加的索引是否是已有的多列索引的最左前缀。如果是这样的,不用增加索引,因为已经有了(例如,如果你在state、city和zip上建立了索引,那么没有必要再增加state的索引)。

四、通过实例理解单例索引、多列索引以及最左前缀原则

实例:现在我们想查出满足以下条件的用户id:
mysql>SELECT `uid` FROM people WHERE
lname`='Liu'  AND
`fname`='Zhiqun' AND `age`=26 ; 因为我们不想扫描整表,故考虑用索引。

1、单列索引:
ALTER TABLE people ADD INDEX lname (lname);

将lname列建索引,这样就把范围限制在lname='Liu'的结果集1上,之后扫描结果集1,产生满足fname='Zhiqun'的结果集2,再扫描结果集2,找到 age=26的结果集3,即最终结果。

由于建立了lname列的索引,与执行表的完全扫描相比,效率提高了很多,但我们要求扫描的记录数量仍旧远远超过了实际所需 要的。虽然我们可以删除lname列上的索引,再创建fname或者age 列的索引,但是,不论在哪个列上创建索引搜索效率仍旧相似。

2、多列索引:

ALTER TABLE people ADD INDEX lname_fname_age (lame,fname,age);

为了提高搜索效率,我们需要考虑运用多列索引,由于索引文件以B-Tree格式保存,所以我们不用扫描任何记录,即可得到最终结果。

注:在mysql中执行查询时,只能使用一个索引,如果我们在lname,fname,age上分别建索引,执行查询时,只能使用一个索引,mysql会选择一个最严格(获得结果集记录数最少)的索引。

3.最左前缀:顾名思义,就是最左优先,上例中我们创建了lname_fname_age多列索引,相当于创建了(lname)单列索引,(lname,fname)组合索引以及(lname,fname,age)组合索引。

注:在创建多列索引时,要根据业务需求,where子句中使用最频繁的一列放在最左边。

数据库的索引可以加快查询速度,原因是索引使用特定的数据结构(B-Tree)对特定的列额外组织存放,加快存储引擎(索引是存储引擎实现)查找记录的速度。索引优化是数据库优化的最重要手段。        如果查询语句使用索引(通常是where条件匹配索引)就会利用树的结构加快查找,索引会按值查找到要查找的行在表中位置,不需回表查询数据的就是聚簇索引(索引和数据存放在一起)。通常是需要回表再查 复合 索引 是指包含多个列的 索引 ,单一 索引 仅包含一列。不论是哪种 索引 ,都旨在加快SQL查询速度。 复合 索引 最多支持16个列(一定不要这么做!), 索引 是一种有序的数列,复合 索引 也是如此。 相对于单一 索引 ,复合 索引 有一些必须注意的 使用 细节,否则很容易造成 索引 失效,降低查询速度。而要了解这些注意细节,就必须从复合 索引 的作用方式入手。 一、复合 索引 的作用方式 所谓“复合”,那一定是包含有多个,...
我们经常听到一些人说"把WHERE条件里的列都加上 索引 ",其实这个建议非常错误。在多个列上建立单独的 索引 大部分情况下并不能提高 MySQL 的查询性能。 MySQL 在5.0之后引入了一种叫“ 索引 合并”(index merge)的策略,一定程度上可以 使用 表上的多个 单列 索引 来定位指定的行。但是当服务器对多个 索引 做联合操作时,通常需要耗费大量CPU和内存资源在算法的缓存、排序和合并操作上,特别是当其中有些 索引 的选择性不高,需要合并扫描大量的数据的时候。这个时候,我们需要一个 多列 索引 。 利用存储过程插入1000w
复合 索引 是把双刃剑,用好了,极大提高系统性能。用不好,放在数据库中就是一堆垃圾。复合 索引 比单字段 索引 的内部原理更复杂。先说说复合 索引 的2个原则:前缀性和可选性。如果稀里糊涂的滥用符合 索引 ,效果就 适得其反。 假设员工信息表(emp)的(ename,job,mgr)3个字段建立了一个ind_1的 索引 。 select * from emp where ename='a' and job
1. **结构**: - 单列 索引 :针对表的一列创建,只包含该列的值以及行的位置信息。如果这列上有唯一约束或列为排序依据, 索引 可能 包含NULL值。 - 多列 索引 (复合 索引 ):涉及表中 多列 的组合,按照特定顺序排列。这种 索引 可以基于几个列的联合值,如`(列A, 列B)`。 2. **查询效率**: - 单列 索引 :适用于等值查找、范围查找和排序,但对于比较两个或更 多列 的查询,效果不如 多列 索引 。 - 复合 索引 :对于涉及多个列作为筛选条件(特别是最左匹配原则下,即查询从左到右的列与 索引 完全匹配),效率较高。但是如果查询中间的列,前部分 索引 将不再有效。 3. **存储空间**: - 单列 索引 :占用较小的空间,因为只需要考虑一列的数据。 - 多列 索引 :需要更多的空间来存储所有列的组合,尤其是当列数增加时。 4. **更新操作**: - 单列 索引 :插入、删除或修改 单列 数据 影响整个 索引 ,可能影响性能。 - 多列 索引 :复杂度更高,因为涉及到多个列的更新。 5. **适用场景**: - 单列 索引 通常用于经常独立搜索或排序的列。 - 多列 索引 适用于复合搜索条件或者频繁按照多个列进行分组、聚合或联合查询的场景。