面试有段时间了,问了很多应聘者数据库索引相关的知识,但是能很好回答的不多,很遗憾,我也想留住你。..面试官:你学过数据库索引吗?应聘者:听说过一些,底层数据结构好像是二叉树,不对,好像是B树,哦,我想起来了,好像是B+树……我)面试官:你听说了吗哈希索引?应聘者:我知道哈希表,但没听说过哈希索引面试官:今天面试来了,回去等消息吧……温馨提示:本文是一篇数据库索引的简单入门文章,以及后面会通过图解逐步给大家介绍索引的原理,敬请期待!先介绍一个简单的例子,通过例子操作说明为什么需要数据库索引。假设我们有一个名为t_employee的数据库表。这个数据库表有姓名、年龄、地址三列,数据量有几万行。如果我们要查找名为“雷小帅”的所有员工的详细信息,只需要写一个简单的SQL语句,相信大家都能写出来。SELECT*FROMt_employeeWHEREname='leixiaoshuai'如果没有索引会怎样?一旦我们运行这个SQL查询,它在数据库中是如何工作的?数据库查找t_employee表中的每一行,确定员工的姓名(name)为'leixiaoshuai'。由于我们要获取每一个名字为雷小帅的员工的信息,所以不能在找到第一行符合条件后就停止查询,因为可能还有其他行符合条件。所以需要逐行查找到最后一行,也就是说数据库要查几万行数据才能找到所有叫雷小帅的员工。这称为全表扫描。数据库索引如何帮助提高性能?你可能会想:“这么简单的查询语句还需要全表扫描,数据库是不是太笨了?!”这类似于用人眼从头到尾逐字逐句地阅读一本书。太低!那我们该怎么办呢?你一定很聪明,想到了一个解决方案:“添加索引”。这就是索引派上用场的地方,使用索引的目的是通过减少表中需要检查的记录/行数来加快搜索查询。**简单的说:“索引就是用来加速查询的。”什么是索引?那么问题来了,什么是索引?索引本质上是一种数据结构(最常见的是B+树),它是在表的列上创建的。索引的数据结构是什么?常见的MySQL索引一般分为:哈希索引和**B+**树索引。InnoDB引擎中默认的是B+树。B+树是最常用的索引数据结构,时间复杂度低:查找、删除、插入操作都可以在logn时间内完成。还有一个重要的原因就是B+树中存储的数据是有序的。B+树常规检索场景下,从根节点到叶节点的查找效率基本一致,不会出现较大的波动。另外,在基于索引的顺序扫描时,还可以利用双向指针快速左右移动,效率很高。哈希索引使用一定的哈希算法将键值转换为新的哈希值。查找的时候不需要像B+树那样从根节点到叶子节点一步步查找。只需要一种哈希算法就可以立即定位到对应的位置,速度非常快。哈希表索引如何工作?如果在创建索引时将数据结构指定为“哈希表”,那么这些索引也可以称为“哈希索引”。哈希索引的优势非常明显。在某些场景下,哈希表在检索指定值时效率极高。比如我们上面讨论的一条查询语句:SELECT*FROMt_employeeWHEREname='leixiaoshuai',如果在name列上加一个hash索引,检索速度可能会提高一倍。哈希索引的工作方式是用列的值作为索引的键值(key),键值对应的实际值(value)是指向表中对应行的指针。因为哈希表基本上可以看作是关联数组,一个典型的数据项就像“雷小帅=>0x996996”,而0x996996是对内存表中雷小帅所在行的引用。在hash索引中查询雷小帅这样的值,得到内存中对应行的引用,显然比扫描全表得到雷小帅值的行要快得多。哈希索引的缺点上面说了哈希索引的优点,但是也绕不开哈希索引的缺点。哈希表是一种不健全的数据结构,哈希索引对很多类型的查询语句无能为力。例如,假设您要查找所有40岁以下的员工。如何使用哈希索引进行查询?这是不可行的,因为哈希表只适合查询键值对,也就是查询相等性的查询(eg:like"WHEREname='leixiaoshuai')。哈希表的keyvaluemap也隐含着它的键的存储是无序的。这就是为什么哈希索引通常不是数据库索引的默认数据结构,因为它们在用作索引数据结构时不如B+Tree灵活。总结缺点:(1)不支持范围查询(2)不支持索引完成排序(3)不支持联合索引的最左前缀匹配规则还有哪些类型的索引?常见的有:R树和位图索引。R树通常用来帮助解决空间问题,比如一个查询需要“找到离我两公里以内的所有麦当劳”,如果数据库表使用R树索引,会提高这类查询的效率。位图索引(位图索引),这种索引适用于列包含布尔值(true和false)。索引如何提高性能?因为索引基本上是用于存储列值的数据结构,这使得查找这些列值的速度更快。如果索引使用的是B+树数据结构,那么里面的数据是有序的,对列值进行排序可以大大提高性能。如果我们在name列上创建B+树索引,意味着当我们使用前面的SQL查找name='leixiaoshuai'时,不需要扫描全表,而是使用索引搜索来查找employee命名为'雷小帅',因为索引已经按字母顺序排序。索引已经排序了,这意味着查询姓名会快很多,因为姓名小于字母'L'的员工排列在一起。另外很重要的一点是,索引中还存储了表中对应行的指针,用于获取其他列的数据。数据库索引中到底存储了什么?你现在我们知道,数据库索引是在表的某一列上创建的,并存储了这一列的所有值。但要理解的重点是,数据库索引不存储表中其他列(字段)的值。例如,如果我们在name列上创建索引,age和address列上的值将不会存储在该索引中。如果我们将所有其他字段存储在这个索引中,它会占用太多空间并且效率很低。索引还存储指向表行的指针。如果我们在索引中找到一条记录作为被索引列的值,那么如何找到这条记录的其他值呢?这个很简单,数据库索引也存储了指向表中相应行的指针。指针指向一块内存区域,内存区域记录了对硬盘上记录的对应行数据的引用。因此,索引除了存储列的值外,还存储了一个指向行数据的索引。也就是说,索引中name列的某个值(或节点)可以描述为(“雷小帅”,0x996996),0x996996是“雷小帅”这一行数据在硬盘上的地址。如果没有这个引用,你只能访问单个值(“雷小帅”),这是没有意义的,因为你无法获取该行记录的员工的其他值——比如地址(address)和年龄(年龄)。数据库如何知道何时使用索引?当您运行查询SQL语句时,数据库会检查查询的列上是否有索引。假设确实在name列上创建了索引,那么数据库会检查使用这个索引进行查询是否合理,因为在某些场景下,使用索引会比全表扫描效率低。你能强制数据库在查询中使用索引吗?通常,您不会告诉数据库何时使用索引,数据库会自行决定。如何在SQL中创建索引?下面是在前面的例子中在Employee_Name列上创建索引时实际的SQL看起来像:CREATEINDEXname_indexONt_employee(name)创建联合索引,SQL如下:CREATEINDEXage_address_indexONt_employee(age,address)数据库索引可以比较什么到?一个很好的类比就是把数据库索引看成书的索引。如果从头到尾一个字一个字地读,就是“全表扫描”;使用数据库索引的成本是多少?既然索引有这么多优点,那么给所有列加索引是不够的,不不不,加索引是有成本的。(1)索引占用空间。表越大,索引占用的空间就越多。(2)更新操作存在性能损失。当您在表中添加、删除或更新行时,索引中也会发生同样的情况。基本原则是:如果表中的某列在查询过程中使用频率很高,则在该列上创建索引。参考:数据库索引如何工作?而且,索引有何帮助?提供数据库索引教程。说说数据库索引--完--好了,以上就是对数据库索引的介绍,也可以说是一篇入门文章。后面我们会通过图解逐步向大家介绍索引的原理,敬请期待!
