1、索引简介
索引是帮助MySQL高效获取数据的排好序的数据结构。
2、 优势
- 类似大学图书馆建书目索引,提高数据检索的效率,降低数据库的IO成本;
- 通过索引列队数据进行排序,降低数据排序的成本,降低了CPU的消耗;
3、 劣势
- 降低更新表的速度,如UPDATE、INSERT和DELETE。因为更新表时,不仅保存数据还要去更新索引文件;
- 实际上索引也是一张表,该表保存了主键与索引字段,并指向实体表,所以索引也是要占用空间的;
4、索引结构
数据结构:B+Tree;
聚簇索引(innobe)的叶子节点就是数据节点 而非聚簇索引(myisam)的叶子节点仍然是索引文件 只是这个索引文件中包含指向对应数据块的指针。
5、索引分类
- 普通索引(KEY)- 即一个索引只包含单个列;
语法:ALTER TABLE 'table_name' ADD INDEX index_name('col'); - 唯一索引(UNIQUE)- 索引列的值必须唯一,但允许空值;
语法:ALTER TABLE 'table_name' ADD UNIQUE INDEX index_name('col'); - 主键索引(PRIMARY KEY)- 一张表只能有一个主键索引,不允许重复,不允许控制;
语法:ALTER TABLE 'table_name' ADD PRIMARY KEY index_name('col'); - 全文索引(FULLTEXT) - 用大文本对象的列构建的索引
语法:ALTER TABLE 'table_name' ADD FULLTEXT INDEX index_name('col');
- 组合索引 - 多个列组合语法:ALTER TABLE 'table_name' ADD
- 遵循“最左前缀”原则,把最常用作为检索或排序的列放在最左,依次递减,组合索引相当于建立了col1,col1col2,col1col2col3三个索引,而col2或者col3是不能使用索引的。
- 在使用组合索引的时候可能因为列名长度过长而导致索引的key太大,导致效率降低,在允许的情况下,可以只取col1和col2的前几个字符作为索引
- index_name('col1','col2'...);
ALTER TABLE 'table_name' ADD INDEX index_name(col1(4),col2(3));
表示使用col1的前4个字符和col2的前3个字符作为索引;
6、哪些情况需要创建索引
- 主键自动建立唯一索引;
- 频繁作为查询条件的字段应该创建索引;
- 查询中与其他表关联的字段,外键关系建立索引;
- 单键组合索引的选择问题,组合索引性价比更高;
- 查询中排序的字段,排序字段若通过索引去访问将大大提高排序速度;
- 查询中统计如使用了max(column_1)或者count(column_1)或者分组字段;
7、哪些情况不要创建索引
- 表记录太少;如果在测试数据库里只有几百条数据记录,它们往往在执行完第一条查询命令之后就被全部加载到内存里,这将使后续的查询命令都执行得非常快--不管有没有使用索引。只有当数据库里的记录超过了1000条、数据总量也超过了MySQL服务器上的内存总量时,数据库的性能测试结果才有意义。
- 经常增删改的表或者字段;
- where条件里用不到的字段不创建索引;
- 有大量重复的列不建立索引:比如性别就男女几个值;
8、索引失效分析
- 组合索引(最佳左前缀法则),查询从索引的最左前列开始并且不跳过索引中的列;
- 组合索引,范围查询条件导致其右边的查询条件索引失效;
- 不在索引列上做任何操作(计算、函数、(自动or手动)类型转换),会导致索引失效而转向全表扫描;
- 在查询条件中使用不等于会导致索引失效转为全表扫描。如果对主键索引使用 !=则不会使索引失效,如果对主键索引或者整数类型的索引使用<符号或者>符号不会使索引失效。(不等于,包括<符号、>符号和!);
- is not null也无法使用索引,但是is null 是可以使用索引的;
- LIKE操作中,'%aaa%'不会使用索引,也就是索引会失效,但是‘aaa%’可以使用索引;
- 字符串不加单引号会导致索引失效。更准确的说是类型不一致会导致失效,比如字段email是字符串类型的,使用WHERE email=99999 则会导致失败,应该改为WHERE email='99999';
- 在一个SELECT语句中,索引只能使用一次,如果在WHERE中使用了,那么在ORDER BY中就不要用了
- 在查询条件中使用OR连接多个条件会导致索引失效,除非OR链接的每个条件都加上索引,这时应该改为两次查询,然后用UNION ALL连接起来
9、建立索引建议
- 对于单列索引,尽量选择针对当前query过滤性更好的索引;
- 在选择组合索引的时候,当前query中过滤性最好的字段在索引字段顺序中,位置越前越好;
- 在选择组合索引的时候,尽量选择可以能够包含当前query中的where字句中更多字段的索引;
- 在选择组合索引的时候,如果某个字段可能出现范围查询时,尽量把这个字段放在索引次序的最后面;
- 书写sql语句时,尽量避免造成索引失效的情况;