索引是对数据库表中一列或多列的值进行排序的一种数据结构。其可以快速访问数据库表中的特定信息。
索引一般以文件形式存在磁盘中(也可以存储在内存中),存储索引的原理即以空间换时间,数据库在未添加索引时是对表进行全局扫描,建立索引后,会将索引的key放在某种数据结构上(B树,B+树)
优点:
缺点
基本索引类型
索引创建的基本语句
create table table_name [col_name data type] [unique|fulltext] [index|key][index_name](col_name[length])[asc|desc]
使用alter table 来创建索引
alter table table_name add index index_name(列1,列2...)创建普通索引
alter table table_name add unique index_name(列1,列2...)创建唯一索引
alter table table_name add primary key (列1,列2...)创建主键
使用create来创建索引
create index index_name on table_name(列1,列2...)创建普通索引
create unique index index_name on table_name(列1,列2...)创建唯一索引
删除索引
drop index index_name on table_name
哪些情况不应该使用索引
数据库建立索引常用规则
即索引的访问规则,什么时候索引的访问可能会失效等。
在MySQL中索引的数据结构一般为B+树和哈希索引
无论是innodb还是myisam都是采用的B+树作为索引的数据结构
mysql的索引又分为聚簇索引和非聚簇索引(二级索引)
mysql中只有memory引擎才支持哈希索引,该索引在哈希表中只包括哈希值和行指针。即先将键计算为哈希值,然后在表中存放哈希值和行指针,哈希索引采用拉链法来解决哈希冲突
所谓聚簇索引是指主键索引文件和数据文件为同一份文件,聚簇索引主要用在innodb存储引擎,该索引实现方式中,B+树的叶子节点上的data是数据本身,key为主键,如果是一般索引那么data中为对应的主键
优点:
缺点:
对于聚簇索引,最好采用自增的主键值,应尽量使用连续增长的值(自增),而不要是随机值
非聚簇索引分为两种,一种是innodb的,其和聚簇索引的区别在于,其在data域中存放的是对应的主键值
所以在对二级索引(非主键索引)进行查询时,在找到对应的叶子节点后,通过查找到对应的主键再去聚簇索引中查找相应的数据行。(使用主键值作为数据的好处在于,如果数据行发生移动,不用更新相应的行指针)
myisam的非聚簇索引
myisam的数据分布实际就是数据的插入顺序,即在Myisam中数据的插入顺序就是数据的排列顺序,myisam的索引也是采用B+树的结构,不过其页中存放的是指向数据表中改行的指针
myisam的主键索引与非主键索引结构相同,只不过主键索引索引值唯一且不为空。
总之,聚簇索引相对非聚簇索引而言,聚簇索引查找数据不用回行查找,其查找效率更高,但是主键选取最好和数据无关,而使得数据的插入是顺序插入,最好避免随机的聚簇索引
sql如果只需要通过索引就可以返回查询所需要的数据,而不必回表查询查询数据,则称此时该索引为覆盖索引,索引是高效找到行的一个方法,当能够通过检索索引就可以读取想要的数据时,那就不需要再用到数据表中读取行了。(如果一个索引包含或者覆盖了满足查询语句中字段与条件的数据就叫做覆盖索引),说白了,就是需要查询的数据就在索引文件中
不是所有类型的索引都可以成为覆盖索引的,覆盖索引必须要存储索引的列,而哈希索引、空间索引、全文索引等不存储索引的列
mysql查询优化器在执行查询前会判断,当前是否有一个索引能进行覆盖,假设索引覆盖了where条件中的字段,但是不是整个查询涉及的字段,也会回表查询。
可以采用覆盖索引进行索引进行优化的几种情况:
覆盖索引与二级索引
如果要查询的就是表的主键,则当使用二级索引时,在查找到表的主键就停止,不用再去聚簇索引查找
myisam中使用前缀压缩来减少索引的大小,从而可以将更多的索引放入内存中。
如果索引列的长度很大,也可以通过只使用该索引列开始的部分字符来作为索引列,这样可以大大节约索引空间,提高索引的效率。
前缀索引的建立原则,即使用多长的前缀?
在一个多列的B/B+树索引中,索引列的顺序意味着索引首先按照最左列进行排序,其次是第二列。。。
顺序选择的经验法则:将选择性最高的列放在索引的最前列。(即索引的基数要高,即这一个列中不重复的元素多)
上面这种方法是一种通用方法,但是也要考虑到经常查询的条件/排序/分组等情况,如果经常用排序/分组,或者经常用某个列来进行查询,则应该将该列放在前面
由于索引本身就是排序的,索引可以用索引来做排序,即将索引列放在order by后面即可。同样最好能够让索引去覆盖待查询的列,这样也可以避免查询一次索引就得回表查询一次记录。
即让索引即用于排序,也用于查询,从而避免回表查询
当多列索引用于排序时,需要注意的是也要遵守最左前缀原则(用于排序的所有索引字段的排序方向必须相同),即order by后面的列要遵循最左前缀原则,但是也有一个特例,就是例如索引(A,B,C),那么如果A在where中被指定为一个常量,则order by后可以从B开始(但是不能从C开始)(注意区分和group by的区别)