9.1.1 索引是什么
索引是一个单独的、存储在磁盘上的数据库结构,它们包含着对数据库表里所有记录的引用指针。使用索引用于快速找出在某个或者多个列中有一特定值的行。对相关列使用索引是提高查询操作速度的最佳途径。
如果有2万条记录,现在执行:SELECT * FROM table WHERE num = 10000;如果没有索引,那么需要遍历整个表,直到找到这一行为止。如果在num这列上建立索引,MySQL将不需要任何扫描,直接在索引里面找10000,就可以得知这一行的位置。
原来,索引就是把这一列的数据单独抽取出来,下次查询的时候,不需要查询以前的表,只需要查询索引,然后在索引中找到了那条数据以后,返回那条数据在表中的位置。那么就可以精确的在表里定位到那条记录的位置,从而避免全表扫描。
索引的优点:
(1)创建唯一索引,可以限制表的某列数据唯一,效果就像为那列数据加上了UNIQUE关键字一样。
(2)加快查询速度,这是创建索引最核心的原因。从4秒钟的查询时间变成了几毫秒,简直不可思议。
(3)在使用分组和排序子句进行数据查询的时候,显著减少查询中分组与排序的时间。
索引的缺点:
占空间,难维护。因为索引是存储在物理磁盘上的,所以占磁盘。在数据库中数据修改的时候,索引也会关联变动,降低了数据的维护速度,即维护索引较为耗时。
9.1.2 索引分类
普通索引:MySQL的基本索引,索引列可以插入空值与重复值。
唯一索引:索引列的值必须唯一,但允许为空。效果就像为列加上了UNIQUE关键字。
主键是一种特殊的唯一索引,不允许为空值。
单列索引:一个索引只包含一个列。
组合索引:在多个字段组合上创建的索引,只有在查询条件中使用了这些字段的最左边字段时,索引才会被使用。
这个原则称为"最左前缀"。
9.1.3 索引设计原则
索引数量并非越多越好,因为索引占磁盘空间。且表中数据更改时,索引也会更新。就像目录一样。
对经常用于查询的字段设计索引。索引列尽可能少,避免添加不必要的字段。
数据量小的表不要用索引。就像正文没一两页,还去查目录一样。
不同值较多的列上建立索引。相反,如果列上值较少,比如“男、女”,加了索引只会降低数据更新速度。
在频繁进行排序与分组的表上建立索引。如果排序列有多个,可以建立组合索引。
当唯一性是某种数据的特征时,可以指定唯一索引。
尽量使用短索引。对字符串类型的字段进行索引,如果可能应该指定一个前缀长度。比如在CHAR(255)的列,如果在前10个或者30个字符,多数值是唯一的,则不需要对整个列进行索引。
9.2.1 建表时创建索引
对于组合索引来说,并不是查询哪个字段都会使用索引,而是遵从“最左前缀”。例如,id、name、age组成的组合索引,索引行按照id name age的顺序存放,索引可以使用下面的组合:(id,name,age)、(id,name)、(id,age)、(id)
(name,age)或者name等组合则不能使用索引查询。
possible_keys和key的值为空,说明上述查询语句没有使用索引。
接下来使用多列索引mutiIdx。(address,age),这两个的组合顺序可以颠倒,因为颠倒了也会有顺序最左的address。
根据上述结果来看,查询address与age使用了索引mutiIdx。
另外一种创建索引的写法。
9.2.2 在已经存在的表上创建索引
需求:在name这列上添加普通索引,为dept列添加唯一索引。
查看t_teacher表的索引。
可以看到,执行SQL后,t_teacher表使用了teacName索引。而这个索引是name列对应的索引。
possible_keys是指可能使用的索引, key是指实际使用的索引。
如果要添加组合索引,只需要在括号里用逗号隔开各个列。
9.2.3 删除索引
删除名为teacName的索引。
添加AUTO_INCREMENT约束字段的唯一索引不能被删除。注:因为主键是一种特殊的唯一索引,所以不允许被删除。
删除表中的列的时候,如果删除的列是索引的组成部分,那么该列也会从索引中删除。
如果组成索引的所有列都被删除,那么这个索引将会被删除。
补充 2019年11月18日:今天发现一个非常奇怪的现象。下面的SQL语句死活不走索引。原因是:
type字段类型为varchar,而SQL中是数字类型,所以不走索引。因此,大家也注意一下。需要把 2 修改为 字符串2:"2"。