什么是索引
一个索引是存储的表中一个特定列的值数据结构。索引是在表的列上创建,以协助快速查询、更新数据库表中数据。所以,要记住的关键点是索引包含一个表中列的值,并且这些值存储在一个数据结构中。请记住记住这一点:索引是一种数据结构。
那什么样的数据结构可以作为索引?
B-Tree 是最常用的用于索引的数据结构。因为它们是时间复杂度低, 查找、删除、插入操作都可以可以在对数时间内完成。另外一个重要原因存储在 B-Tree 中的数据是有序的。数据库管理系统通常决定索引应该用哪些数据结构。但是,在某些情况下,你在创建索引时可以指定索引要使用的数据结构。
索引中B+数叶子结点存了哪些信息?
当前节点值+主键值+下一节点的指针。
为什么要加索引,它是怎么提高性能的,在哪列加索引
比方说我们运行以下的 sql 语句
1 | SELECT * FROM Employee WHERE Employee_Name = 'Jesus' |
一旦我们运行这个查询由于我们想要得到每一个名字为 Jesus 的雇员信息,在查询到第一个符合条件的行后,不能停止查询,因为可能还有其他符合条件的行。所以,必须一行一行的查找直到最后一行,这就意味数据库不得不检查上千行数据才能找到所以名字为 Jesus 的雇员。这就是所谓的全表扫描。
使用索引的话,因为索引基本上是用来存储列值的数据结构,这使查找这些列值更加快速。如果索引使用最常用的数据结构 B-Tree那么其中的数据是有序的。假设我们在 Employee_Name这一列上创建一个B-Tree索引,索引已经排序意味着查询一个名字会快很多,因为名字少字母为‘J’的员工都是排列在一起的。另外重要的一点是,索引同时存储了表中相应行的指针以获取其他列的数据。
因此索引的全部意义就是通过缩小一张表中需要查询的记录/行的数目来加快搜索的速度。
那么在创建索引的时候,应该考虑在哪些列上可以创建索引,在哪些列上不能创建索引:
一般来说,应该在这些列上创建索引:
- 在经常需要搜索的列上,可以加快搜索的速度;
- 在作为主键的列上,强制该列的唯一性和组织表中数据的排列结构;
- 在经常用在连接的列上,这些列主要是一些外键,可以加快连接的速度;
- 在经常需要根据范围进行搜索的列上创建索引,因为索引已经排序,其指定的范围是连续的;
- 在经常需要排序的列上创建索引,因为索引已经排序,这样查询可以利用索引的排序,加快排序查询时间;
- 在经常使用在WHERE子句中的列上面创建索引,加快条件的判断速度。
不应该创建索引的的这些列具有下列特点:
对于那些在查询中很少使用或者参考的列不应该创建索引。这是因为,既然这些列很少使用到,因此有索引或者无索引,并不能提高查询速度。相反,由于增加了索引,反而降低了系统的维护速度和增大了空间需求。
对于那些只有很少数据值的列也不应该增加索引。这是因为,由于这些列的取值很少,例如人事表的性别列,在查询的结果中,结果集的数据行占了表中数据行的很大比例,即需要在表中搜索的数据行的比例很大。增加索引,并不能明显加快检索速度。
对于那些定义为 text , image 和 bit 数据类型的列不应该增加索引。这是因为,这些列的数据量要么相当大,要么取值很少。
当修改性能远远大于检索性能时,不应该创建索引。这是因为,修改性能和检索性能是互相矛盾的。
索引的好处和缺点
好处
- 通过创建唯一性索引,可以保证数据库表中每一行数据的唯一性。
- 可以大大加快数据的检索速度,这也是创建索引的最主要的原因。
- 可以加速表和表之间的连接,特别是在实现数据的参考完整性方面特别有意义。
- 在使用分组和排序子句进行数据检索时,同样可以显著减少查询中分组和排序的时间。
- 通过使用索引,可以在查询的过程中,使用优化隐藏器,提高系统的性能。
缺点
- 创建索引和维护索引要耗费时间,这种时间随着数据量的增加而增加。
- 索引需要占物理空间,除了数据表占数据空间之外,每一个索引还要占一定的物理空间,如果要建立聚簇索引,那么需要的空间就会更大。
- 当对表中的数据进行增加、删除和修改的时候,索引也要动态的维护,这样就降低了数据的维护速度。
什么时候索引会失效
- 条件中有or
- 对于多列索引,不是使用的第一部分(第一个),则不会使用索引
- like查询是以%开头
- 如果列类型是字符串,那一定要在条件中将数据使用引号引用起来,否则不使用索引
- 使用全表扫描要比使用索引快,则不使用索引
索引存了哪些内容
数据库索引是创建在表的某列上的,并且存储了这一列的所有值。但是,数据库索引并不存储这个表中其他列(字段)的值,同时索引还存储了指向表中某一行的指针。
索引种类
- 唯一索引:UNIQUE 例如:create unique index stusno on student(sno);
表明此索引的每一个索引值只对应唯一的数据记录,对于单列惟一性索引,这保证单列不包含重复的值。对于多列惟一性索引,保证多个值的组合不重复。 - 主键索引: primary key
数据库表经常有一列或列组合,其值唯一标识表中的每一行。该列称为表的主键。 在数据库关系图中为表定义主键将自动创建主键索引,主键索引是唯一索引的特定类型。该索引要求主键中的每个值都唯一。当在查询中使用主键索引时,它还允许对数据的快速访问。 - 聚集索引(也叫聚簇索引):cluster
在聚集索引中,表中行的物理顺序与键值的逻辑(索引)顺序相同。一个表只能包含一个聚集索引。 如果某索引不是聚集索引,则表中行的物理顺序与键值的逻辑顺序不匹配。与非聚集索引相比,聚集索引通常提供更快的数据访问速度。
根据实现方式
- 聚集索引
- 非聚集索引
- 哈希索引
- B+-树索引(二分查找)
聚集索引,表数据按照索引的顺序来存储的。对于聚集索引,叶子结点即存储了真实的数据行,不再有另外单独的数据页。但是非聚集索引,表数据存储顺序与索引顺序无关。对于非聚集索引,叶结点包含索引字段值及指向数据页数据行的逻辑指针,该层紧邻数据页,其行数量与数据表行数据量一致。
这样的结果就是取出一定范围内的数据使用聚集索引比较好,而且当通过聚簇索引查找目标数据时理论上比非聚簇索引要快,因为非聚簇索引定位到对应主键时还要多一次目标记录寻址,即多一次I/O。但是插入速度严重依赖于插入顺序。
唯一索引和主键索引
主键索引是特殊的唯一索引,每个表只能建一个,但是唯一索引能建多个
主健可作外健,唯一索引不可
主健不可为空,唯一索引可以。
索引原理
就是底层使用的数据结构,然后可以介绍一下索引的优缺点
单列和联合索引
为了提高数据库效率,建索引是家常便饭;那么当查询条件为2个及以上时,我们是创建多个单列索引还是创建一个联合索引,也就是我们需要挑选的。
复合索引的结构与电话簿类似,人名由姓和名构成,电话簿首先按姓氏对进行排序,然后按名字对有相同姓氏的人进行排序。如果您知道姓,电话簿将非常有用;如果您知道姓和名,电话簿则更为有用,但如果您只知道名不姓,电话簿将没有用处。但是建议列数最多不要越过3列否则虽然减少了回表动作,但索引块过多,查询时就要遍历更多的索引块了
创建复合索引时,应该仔细考虑列的顺序。对索引中的所有列执行搜索或仅对前几列执行搜索时,复合索引非常有用;仅对后面的任意列执行搜索时,复合索引则没有用处。当创建 (a,b,c) 联合索引时,相当于创建了 (a) 单列索引,(a,b) 联合索引以及 (a,b,c) 联合索引想要索引生效的话,只能使用 a和a,b和a,b,c三种组合;当然 a,c 组合也可以,但实际上只用到了 a 的索引,c 并没有用到!
这个也就是我们常见的最左匹配原则顾名思义是最左优先,以最左边的为起点任何连续的索引都能匹配上,
注:如果第一个字段是范围查询需要单独建一个索引
注:在创建联合索引时,要根据业务需求,where子句中使用最频繁的一列放在最左边。这样的话扩展性较好,比如 userid 经常需要作为查询条件,而 mobile 不常常用,则需要把 userid 放在联合索引的第一位置,即最左边
什么时候该用联合索引以及如何设计组合索引更高效
- 等值查询中,查询条件 a 返回的条目比较多,查询条件 b 返回的条目比较多,而同时查询 a、b 返回的条目比较少,那么适合建立联合索引;
- 对于有等值查询的列和范围查询的列,等值查询的列建在前、范围查询的列建在后比较实用;
- 如果联合索引列的前置列与索引单列一致,那么单列查询可以用到索引,这样就避免了再建单列索引,因此联合索引的前置列应尽量与单列一致;
联合索引题目
有ABCD,建立了index(A,C,D)
查A = xx and D = xx可以吗
查C = xx and D = xx可以吗
查C = xx and A = xx可以吗
答:部分索引 无索引 部分索引
什么时候使用B+索引
当查询表中很少一部分数据时,B+ 索引才有意义。对于性别,地区类型字段,他们取值范围很小,即低选择性。这时加 B+ 索引是没有必要的。相反,某个字段取值范围很广,如姓名,几乎没有重复,即高选择性,则使用B+索引是比较合适的。因此。当访问高选择性字段并取出很少一部分数据时,该字段加 B+ 索引是非常有效的。但是当取出的数据行占表中大部分数据时,数据库就不会使用 B+ 索引了。