导论:
想象这样一个场景:地上有500个汉字小卡片,我想让你找到“我”这个汉字,你会怎么做?
朴素的解决思路是:拿起第一张小卡片,看看是不是“我”,是的话提交,不是的话,拿起第二张小卡片……
由于每个小卡片都可能命中这个汉字(也可能这500个小卡片里都没有“我”这个字),因此其时间复杂度为O(n)。
问题来了:如果有300个人,分别让你查找不同的汉字,这样的查找效率实在是太低了。
假设看一张卡片1秒,看250张卡片能确保找到需要的汉字,这300个人排队查找,那么时间为1*250*300=20.833(小时)。
我们如何改善解决方案?大概你已经想到了,将数据排序,提供像是字典一样的工具,不就行了?
索引,就是一个用于优化查找、排序好的数据结构,一般是B树或哈希。
索引的创建:
一般用SQL语句创建索引,也可以使用图形工具如navicat创建。
sql语句为:CREATE INDEX index_name ON table_name(column_name);
例如,在表users中,创建一个以name为索引列的、叫做test的索引:
CREATE INDEX test ON users(name);
对于联合索引(即针对多个列的索引),创建语法一致:
sql语句为:CREATE INDEX index_name ON table_name(column_name1, column_name2);
索引的使用:
索引在创建出来后,会持久保存在数据库DBS中,也就是无论哪个DBMS数据库操作软件,都可以使用你定义好的索引。
索引无需显式使用,在进行查找操作时,数据库会根据需要自动使用。
索引搜索带来的问题:
我们知道,索引解决查找慢的问题,本质是将这些数据排好序,那么就必然会涉及到存储、“写”操作等问题。
首先,索引会降低“写”操作(即插入、删除、修改)的效率,因为每次“写”操作,都可能使数据库重新排序索引中的数据。
其次,如果在数据库中有大量索引,很可能占用大量存储空间。
建立索引考虑的基本因素:
最重要的两点:该列的值是否频繁更新?(相对于“读”操作,“写”操作占比多吗?)、该列值的选取范围(该列可能值有哪些?100个还是200个?)
1.值是否频繁更新:如上,我们已知索引会降低“写”操作的效率,如果数据库的数据频繁更新,那么反而会降低整体运行效率。
2.选取范围:指的不止是可能值,还包括值的分布。
如果一个列“gov”,只能填写3个数值,如a市下属3个区b、c、d。那么,如果有一万条数据,它们基本上都是重复的,建立索引对效率的提升很少。
如果这个列是“name”,有无数取值,一万条数据,可能只有几个重复的,那么查找起来,效率提升极多。
照样是“gov”列,取值可以是全球各地的区级单位(有无数可能),但是只在a市采样,这里可能百分之99的人都是a市土生土长的,一万条数据,9900条都是a市本地的,那么建立索引后,效率的提升也不明显。
此外,建立索引要避免使用主键,因为主键具有唯一性,故数据库一般会为主键自动创建一个索引,我们再次建立会浪费空间。
索引应该做到定期更新,因为在数据库更新的过程中,索引可能会变得不那么好用,比如某个列本来所有的值都是唯一的,在数据更新途中数据列一点点同化,变得重复性极高,也不利于索引提升效率。
MySQL四种索引类型与作用:
- normal索引:最常用的索引,允许数据库的索引列中,值相同;
- unique索引:自带唯一性约束的索引,如果数据库的索引列有值相同会报错;
- fulltext索引:富文本索引,指的是针对文本字段的优化索引;
- spatial索引:针对地理空间类型的数据建立的优化索引。
以上内容即我想分享的关于数据库索引的一些知识。
我是蚊子码农,如有补充,欢迎在评论区留言。个人也是初学者,知识体系可能没有那么完善,希望各位多多指正,谢谢大家。