数据库索引

本篇文章我们来了解下数据库索引,首先什么是数据库索引?
数据库索引 是为了加快查询速度对表的字段增加的一种标识。DB在执行sql语句的时候,如果没有索引,将会根据搜索条件进行全局遍历,如果对某一字段增加索引,会根据索引定位数据具体所在的位置,减少了查找的次数,加快了操作速度。索引的实现通常使用B树及其变种B+树。

创建索引可以大大提高系统的性能:
1.通过创建唯一性索引,可以保证数据库表中每一行数据的唯一性。
2.可以大大加快数据的检索速度,这也是创建索引的最主要的原因。
3.可以加速表和表之间的连接,特别是在实现数据的参考完整性方面特别有意义。
4.在使用分组和排序子句进行数据检索时,同样可以显著减少查询中分组和排序的时间。
5.通过使用索引,可以在查询的过程中,使用优化隐藏器,提高系统的性能。

但也有一些不利的地方:
1.创建索引和维护索引要耗费时间,这种时间随着数据量的增加而增加。
2.索引需要占物理空间,除了数据表占数据空间之外,每一个索引还要占一定的物理空间,如果要建立聚簇索引,那么需要的空间就会更大。
3.当对表中的数据进行增加、删除和修改的时候,索引也要动态的维护,这样就降低了数据的维护速度。

索引是建立在数据库表中的某些列的上面。在创建索引的时候,应该考虑在哪些列上可以创建索引,在哪些列上不能创建索引。一般来说,应该在这些列上创建索引:
1.在经常需要搜索的列上,可以加快搜索的速度;
2.在作为主键的列上,强制该列的唯一性和此列的物理排列结构;
3.在经常用在连接的列上,这些列主要是一些外键,可以加快连接的速度;
4.在经常需要根据范围进行搜索的列上创建索引,因为索引已经排序,其指定的范围是连续的;
5.在经常需要排序的列上创建索引,因为索引已经排序,这样查询可以利用索引的排序,加快排序查询时间;
6.在经常使用在WHERE子句中的列上面创建索引,加快条件的判断速度。

也有不适合创建索引的列:
1.对于那些在查询中很少使用或者参考的列不应该创建索引。这是因为,既然这些列很少使用到,因此有索引或者无索引,并不能提高查询速度。相反,由于增加了索引,反而降低了系统的维护速度和增大了空间需求。
2.对于那些只有很少数据值的列也不应该增加索引。这是因为,由于这些列的取值很少,例如人事表的性别列,在查询的结果中,结果集的数据行占了表中数据行的很大比例,即需要在表中搜索的数据行的比例很大。增加索引,并不能明显加快检索速度。
3.对于那些定义为image和bit数据类型的列不应该增加索引。这是因为,这两种类型数据量要么相当大,要么取值很少。
4.当修改性能远远大于检索性能时,不应该创建索引。这是因为,修改性能和检索性能是互相矛盾的。当增加索引时,会提高检索性能,但是会降低修改性能。当减少索引时,会提高修改性能,降低检索性能。因此,当修改性能远远大于检索性能时,不应该创建索引。

数据库索引可以分为主键索引、唯一索引、普通索引、组合索引、全文索引(MySQL 5.6 以前的版本,只有 MyISAM 存储引擎支持全文索引,MySQL 5.6 及以后的版本,MyISAM 和 InnoDB 存储引擎均支持全文索引)。这个就不详细介绍了,相信大家都比较熟。

从另一种角度,索引也可以分为聚集索引和非聚集索引,聚集索引是指数据库表行中数据的物理顺序与键值的逻辑(索引)顺序相同,也就是说该索引中键值的逻辑顺序决定了表中相应行的物理顺序,所以一张表中只能有一个聚集索引,mysql中,聚集索引通常是主键索引,若无主键则为表中第一个非空的唯一索引,还是没有就采用innodb存储引擎为每行数据内置的ROWID作为聚集索引。

mysql的存储引擎分为myisam和innodb:

  • myisam是mysql默认的引擎,但是它没有提供对数据库事务的支持,也不支持行级锁和外键,因此当insert(插入)或update(更新)数据时即写操作需要锁定整个表,效率便会低一些。不过和innodb不同,myisam中存储了表的行数,于是select count(*) from table时只需要直接读取已经保存好的值而不需要进行全表扫描。如果表的读操作远远多于写操作且不需要数据库事务的支持,那么myisam也是很好的选择。
  • innodb引擎提供了对数据库ACID事务的支持,并且实现了SQL标准的四种隔离级别。该引擎还提供了行级锁和外键约束,它的设计目标是处理大容量数据库系统。当需要使用数据库事务时,该引擎当然是首选。由于锁的粒度更小,写操作不会锁定全表,所以在并发较高时,使用innodb引擎会提升效率。但是使用行级锁也不是绝对的,如果在执行一个SQL语句时MySQL不能确定要扫描的范围,innodb表同样会锁全表。

局部性原理
由于存储介质的特性,磁盘本身存取就比主存慢很多,再加上机械运动耗费,磁盘的存取速度往往是主存的几百分分之一,因此为了提高效率,要尽量减少磁盘I/O。为了达到这个目的,磁盘往往不是严格按需读取,而是每次都会预读,即使只需要一个字节,磁盘也会从这个位置开始,顺序向后读取一定长度的数据放入内存。这样做的理论依据是计算机科学中著名的局部性原理:当一个数据被用到时,其附近的数据也通常会马上被使用。程序运行期间所需要的数据通常比较集中。
预读的长度一般为页(page)的整倍数。页是计算机管理存储器的逻辑块,硬件及操作系统往往将主存和磁盘存储区分割为连续的大小相等的块,每个存储块称为一页(在许多操作系统中,页得大小通常为4k),主存和磁盘以页为单位交换数据。

索引的数据结构
mysql索引使用B+树结构而不是B树,因为B树只适合随机检索,而B+树同时支持随机检索和顺序检索,同时B+树空间利用率更高,因为B+树的内部节点(非叶子节点,也称索引节点)不存储数据,只存储索引值,相比较B树来说,B+树一个节点可存储更多的索引值,使得整颗B+树变得更矮,减少I/O次数,磁盘读写代价更低,I/O读写次数是影响索引检索效率的最大因素。通常InnoDB的一棵B+树可以存放约2千万行数据(通过网友计算得出),

索引失效的几种情况:
1.当查询条件存在隐式转换时,索引会失效,比如列类型是字符串,查询条件未加引号
2.使用like时通配符在前
3.在查询条件中使用OR,查询条件中使用or会使索引失效,要想使索引生效,需要将or中的每个列都加上索引。
4.对索引列进行函数运算
5.联合索引时,一个查询可以只使用索引中的一部份,但只能是最左侧部分,不支持只使用非左侧部分。
6.not条件,当查询条件为非时,索引定位会比较困难,执行计划此时可能更倾向于全表扫描,这类的查询条件有:<>、NOT、in、not exists。
7.存在NULL值条件,如果索引列是可空的,很可能是不会给其建索引的,索引值是少于表的count(*)值的,所以这种情况下,执行计划自然就去扫描全表了。

引用:
https://blog.csdn.net/weixin_44893585/article/details/104695350
https://blog.csdn.net/kennyrose/article/details/7532032
https://www.zhihu.com/question/20596402/answer/977935094

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

友情链接更多精彩内容