数据库索引

 索引在日常的查询中用的很多,在面试的时间也  经常被问题,用一点时间统一整理下。

什么是索引?

索引就像之前用的字典的拼音,用于快速查找表中的某一条数据或某一些数据。如果没有索引,那么数据库引擎只能全表扫描 ,表越大,扫描的时间  越长,查询的速度越慢。如果表中查询的列有一个索引,MySQL 没有  必要检索全表,可以直接找到某些数据。就好像我们可以根据拼音快速找到某个字在字典中的位置。

MySQL 索引要点

优点

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

缺点

  • 创建索引和维护索引要耗费时间,并且随着数据量的增加所耗费的时间也会增加
  • 索引也需要占空间,我们知道数据表中的数据也会有最大上限设置的,如果我们有大量的索引,索引文件可能会比数据文件更快达到上限值。一般来说,索引表占用的空间的数据表的 1.5 倍;索引表的维护和创建需要时间成本,这个成本随着数据量增大而增大
  • 当对表中的数据进行增加、删除、修改时,索引也需要动态的维护索引表,降低了数据的维护速度。

使用原则

  • 对经常更新的表就避免对其进行过多的索引,对经常用于查询的字段应该创建索引,
  • 数据量小的表最好不要使用索引,因为由于数据较少,可能查询全部数据花费的时间比遍历索引的时间还要短,索引就可能不会产生优化效果。
  • 在一同值少的列上(字段上)不要建立索引,比如在学生表的"性别"字段上只有男,女两个不同值。相反的,在一个字段上不同值较多可是建立索引。
  • 尽量避免 Null,null 会让索引,索引统计和值比较都变得更加复杂,尽量不要在 null 列建索引。

先基本上理解索引,然后等以后真正用到了,就会慢慢知道别的作用。注意,学习这张,很重要的一点就是必须先得知道索引是什么,索引是干嘛的,有什么作用,为什么要索引等等,如果不知道,就重复往上面看看写的文字,好好理解一下。一个表中很够创建多个索引,这些索引度会被存放到一个索引文件中(专门存放索引的地方)。

索引的分类

注意:索引是在存储引擎中实现的,也就是说不同的存储引擎,会使用不同的索引 MyISAM 和 InnoDB 存储引擎:只支持 BTREE 索引, 也就是说默认使用 BTREE,不能够更换 MEMORY/HEAP 存储引擎:支持 HASH 和 BTREE 索引

索引我们分为四类来讲 单列索引(普通索引,唯一索引,主键索引)、组合索引、全文索引、空间索引、

  1. 单列索引:一个索引只包含单个列,但一个表中可以有多个单列索引。 这里不要搞混淆了。

    • 普通索引:MySQL 中基本索引类型,没有什么限制,允许在定义索引的列中插入重复值和空值,纯粹为了查询数据更快一点。
    • 唯一索引:索引列中的值必须是唯一的,但是允许为空值,
    • 主键索引:是一种特殊的唯一索引,不允许有空值。
  2. 组合索引 在表中的多个字段组合上创建的索引,只有在查询条件中使用了这些字段的左边字段时,索引才会被使用,使用组合索引时遵循最左前缀集合。 组合索引:用多个列组合构建的索引,这多个列中的值不允许有空值

    ALTER TABLE 'table_name' ADD INDEX index_name('col1','col2','col3')
    1

    遵循“最左前缀”原则,把最常用作为检索或排序的列放在最左,依次递减,组合索引相当于建立了 col1,col1col2,col1col2col3 三个索引,而 col2 或者 col3 是不能使用索引的。 在使用组合索引的时候可能因为列名长度过长而导致索引的 key 太大,导致效率降低,在允许的情况下,可以只取 col1 和 col2 的前几个字符作为索引

    ALTER TABLE 'table_name' ADD INDEX index_name(col1(4),col2(3))
    1

    表示使用 col1 的前 4 个字符和 col2 的前 3 个字符作为索引

  3. 全文索引 全文索引,只有在 MyISAM 引擎上才能使用,只能在 CHAR,VARCHAR,TEXT 类型字段上使用全文索引, 在实际工作中  并  没有使用过,因为 InnoDB 是用的更普遍的数据库引擎。

  4. 空间索引 空间索引是对空间数据类型的字段建立的索引,MySQL 中的空间数据类型有四种,GEOMETRY、POINT、LINESTRING、POLYGON。在创建空间索引时,使用 SPATIAL 关键字。要求,引擎为 MyISAM,创建空间索引的列,必须将其声明为 NOT NULL。

索引创建和删除

  1. 创建索引

    1. 创建表的时候创建索引
    CREATE TABLE  表名( 属性名 数据类型[完整性约束条件],
        属性名 数据类型[完整性约束条件],
        ......
        属性名 数据类型
        [ UNIQUE | FULLTEXT | SPATIAL ]  INDEX | KEY
        [ 别名]  ( 属性名1  [(长度)]  [ ASC | DESC] )
    );
    
    1
    2
    3
    4
    5
    6
    7
    1. 在创建表之后通过 alter table 命令修改:
    - 添加普通索引: ALTER TABLE t_user ADD INDEX IDX_USER__USER_ID(user_id);
    - 添加唯一索引: ALTER TABLE t_user ADD UNIQUE INDEX IDX_USER__UNQ_USER_ID(user_id);
    - 添加复合索引: ALTER TABLE t_user ADD UNIQUE INDEX IDX_USER__COMP_USER_ID(user_id,user_name);
    
    1
    2
    3

索引的使用策略

  1. 什么时候要使用索引?
  • 主键自动建立唯一索引;
  • 经常作为查询条件在 WHERE 或者 ORDER BY 语句中出现的列要建立索引;
  • 作为排序的列要建立索引;
  • 查询中与其他表关联的字段,外键关系建立索引
  • 高并发条件下倾向组合索引;
  1. 什么时候不要使用索引?
  • 经常增删改的列不要建立索引;
  • 有大量重复的列不建立索引;
  • 表记录太少不要建立索引;
  • 在组合索引中不能有列的值为 NULL,如果有,那么这一列对组合索引就是无效的;
  • 在一个 SELECT 语句中,索引只能使用一次,如果在 WHERE 中使用了,那么在 ORDER BY 中就不要用了;
  • LIKE 操作中,'%aaa%'不会使用索引,也就是索引会失效,但是‘aaa%’可以使用索引;
  • 在索引的列上使用表达式或者函数会使索引失效,例如:select * from users where YEAR(adddate)<2018,将在每个行上进行运算,这将导致索引失效而进行全表扫描,因此我们可以改成:select * from users where adddate<’2018-12-24′。
  • 在查询条件中使用正则表达式时,只有在搜索模板的第一个字符不是通配符的情况下才能使用索引。
  • 在查询条件中使用<>会导致索引失效。
  • 在查询条件中使用 IS NULL 会导致索引失效。
  • 在查询条件中使用 OR 连接多个条件会导致索引失效,这时应该改为两次查询,然后用 UNION ALL 连接起来。
  • 尽量不要包括多列排序,如果一定要,最好为这队列构建组合索引;
  • 只有当数据库里已经有了足够多的测试数据时,它的性能测试结果才有实际参考价值。如果在测试数据库里只有几百条数据记录,它们往往在执行完第一条查询命令之后就被全部加载到内存里,这将使后续的查询命令都执行得非常快--不管有没有使用索引。只有当数据库里的记录超过了 1000 条、数据总量也超过了 MySQL 服务器上的内存总量时,数据库的性能测试结果才有意义。

参考

  • [参考 1]:高可用 MYSQL