18、MySQL索引(基础)

一、概要

索引就像一本书的目录。而当用户通过索引查找数据时,就好比用户通过目录查询某章节的某个知识点。这样就帮助用户有效地提高了查找速度。所以,使用索引可以有效地提高数据库系统的整体性能

在我们的一个应用系统中,读写的比例一般大概8:2左右,在实战开发中,当数据量比较大的时候查询的速度比较慢的时候,我们可以通过创建索引的方式来加快我们的查询速度

二、什么叫索引

系统根据某种算法,将已有的数据(未来可能新增的数据),单独建立一个文件,这个文件能够实现快速匹配数据,并且能够快速的找到对应的记录,本质上是一种数据结构

三、优缺点

1、优点

  • 提升查询数据的效率
  • 可以加速表与表之间的连接
  • 在使用分组和排序进行检索的时候,可以减少查询中分组和排序的时间

2、缺点

  • 当对表中的数据进行增加、删除和修改的时候,索引也要动态的维护,这样就降低了数据的维护速度。
  • 创建索引和维护索引要耗费时间,这种时间随着数据量的增加而增加。
  • 索引需要占物理空间,除了数据表占数据空间之外,每一个索引还要占一定的物理空间,如果要建立聚簇索引,那么需要的空间就会更大。

三、索引分类

1、按存储结构

  1. BTree索引
  2. Hash索引
  3. 位图索引(mysql不支持)

2 、按应用层次

  1. 普通索引,
  2. 主键索引
  3. 唯一索引
  4. 全文索引
  5. 复合索引

3、数据行的物理顺序与列值的逻辑顺序相同

  1. 聚集索引
  2. 非聚集索引

四、基本使用

4.1、主键索引

  1. 说明

    创建主键约束自动会建立主键索引,不允许重复,不允许空值

  2. 语法格式

    -- 创建主键时数据库自动创建
    CREATE TABLE 表名 (
      列名 类型  PRIMARY KEY
    )
    -- 或者 表级创建
    CREATE TABLE 表名 (
      列名 类型 ,
       PRIMARY KEY(列名)
    )
    
  3. 示例代码

    CREATE TABLE t_test(
         -- 自动创建主键索引
         tid int AUTO_INCREMENT  PRIMARY KEY
    )
    -- 或者
    CREATE TABLE t_test(
         -- 自动创建主键索引
         tid int AUTO_INCREMENT ,
         PRIMARY KEY(tid)
    )
    

4.2、普通索引

  1. 说明

    在创建普通索引时,不附加任何限制条件。这类索引可以创建在任何数据类型中,其值是否唯一和非空由字段本身的完整性约束条件决定。

  2. 语法格式

    -- 在创建表的时候创建  (不推荐)
    CREATE TABLE 表名(
         列名 类型 约束,
         ....,
         key ()
    )
    --  创建表之后在创建索引 (推荐方式创建)
    CREATE INDEX 索引名 ON 表 (列名,);
    
  3. 示例代码

    CREATE TABLE t_index_key
    (
        tid  int PRIMARY KEY AUTO_INCREMENT,
        name varchar(64) NOT NULL,
        KEY (name)
    )
    
    -- 删除索引
    DROP INDEX name ON t_index_key
    -- 创建索引 推荐
    CREATE  INDEX  idx_key_name ON t_index_key(name)
    -- 查看索引
    EXPLAIN  SELECT * from t_index_key
    WHERE name='123'
    

4.3、唯一索引

  1. 说明

    用来建立索引的列的值必须是唯一的,允许空值, 可以通过创建表的时候使用唯一约束创建

  2. 语法格式

    CREATE  UNIQUE INDEX 索引名 ON  表名(列名 DESC,列名)
    
  3. 示例代码

    CREATE  UNIQUE INDEX idx_user_username
    ON t_user(username DESC)
    

4.4、全文索引

  1. 说明

    即为全文索引,Mysql5.6之前只有MyISAM引擎支持,Mysql5.6之后InnoDB也支持。目前只有 CHAR、VARCHAR ,TEXT 列上可以创建全文索引

    主要解决 它的出现是为了解决WHERE name LIKE “%word%"这类针对文本的模糊查询效率较低的问题

  2. 创建格式

    -- 1. 创建表
    DROP TABLE IF EXISTS t_myisam;
    CREATE TABLE t_myisam
    (
        mid    int AUTO_INCREMENT PRIMARY KEY,
        name   varchar(64) NOT NULL,
        detail text
    ) ENGINE = MYISAM
      DEFAULT CHARSET = UTF8MB4;
      
    
  3. 查询格式

     MATCH (列名,...) AGAINST ('查询的关键字')
    
  4. 示例代码

    -- 1. 创建
    DROP TABLE IF EXISTS t_myisam;
    
    CREATE TABLE t_myisam
    (
        mid    int AUTO_INCREMENT PRIMARY KEY,
        name   varchar(64) NOT NULL,
        detail text
    
    ) ENGINE = MYISAM
      DEFAULT CHARSET = UTF8MB4;
    
    --  2.创建全文索引
    CREATE FULLTEXT  INDEX idx_username_detail
    ON  t_myisam(detail)
    
    --  查看索引信息
    SHOW INDEX FROM t_myisam
    --  或者
    SHOW  KEYS  FROM  t_myisam
    
    SELECT *
            FROM t_myisam
            WHERE  MATCH(detail) AGAINST('%ab%')
    -- 查看索引是否生效
    
    EXPLAIN SELECT *
            FROM t_myisam
            WHERE  MATCH(detail) AGAINST('%ab%')
    

4.5、联合索引(多列索引)

  1. 说明

    联合索引遵守“最左前缀”原则,即在查询条件中使用了联合索引的第一个字段,索引才会被使用。因此,在联合索引中索引列的顺序至关重要。如果不是按照索引的最左列开始查找,则无法使用索引

  2. 语法格式

    CREATE INDEX  索引名 ON 表名(索引字段,索引字段,...)
    
  3. 示例代码

    CREATE TABLE t_user
    (
        uid         int         AUTO_INCREMENT PRIMARY KEY,
        username    varchar(64)                            NOT NULL,
        password    varchar(128)                        NOT NULL,
        phone       varchar(11)                         NOT NULL,
        is_delete   tinyint   DEFAULT 0                 NOT NULL,
        create_date timestamp DEFAULT CURRENT_TIMESTAMP NOT NULL,
        CONSTRAINT index_user_name
            UNIQUE (username)
    );
    
    --  创建普通的联合索引
    CREATE INDEX index_user_date
        ON t_user (username,phone,create_date);
    
    -- 联合索引字段 username,phone,create_date
    
    -- 1. 可以
    SELECT *
    FROM t_user
    WHERE username = 'admin';
    -- 2. 可以
    SELECT *
    FROM t_user
    WHERE username = 'admin'
      AND phone = '123456';
    -- 3. 可以
    SELECT *
    FROM t_user
    WHERE username = 'admin'
      AND phone = '123456'
      AND create_date = '2019-07-18 17:04:12';
    
    -- 不可以
    SELECT *
    FROM t_user
    WHERE phone = '123456';
    
    
  4. 最左前缀的原则

    • 如果我们建立了一个2列的联合索引(a,b),实际上已经相当于建立了两个联合索引( a ) 、( a, b );
    • 如果有一个3列索引( a, b, c ),实际上已经建立了三个联合索引( a )、(a, b)、(a, b, c)。依次内推
  5. 总结

    当创建(a,b,c)联合索引时,相当于创建了(a)单列索引(a,b)联合索引以及(a,b,c)联合索引
    想要索引生效的话,只能使用 a和a,b和a,b,c三种组合;当然,测试过,a,c组合也可以

五、什么情况使用索引

  1. 索引应该经常建在where 子句经常用到的列上。如果某个大表经常使用某个字段进行查询,并且检索行数小于总表行数的5%。则应该考虑。
  2. 对于两表连接的字段,应该建立索引。如果经常在某表的一个字段进行Order By 则也经过进行索引。
  3. 不应该在小表上建设索引(例如表中只有三四个字段)。

六、索引失效的情况

  1. 对索引列运算,运算包括(+、-、*、/、!、%),导致索引失效

    -- 则会使索引失效,
    EXPLAIN SELECT * FROM tbl WHERE  age + 5 > 10 
    
  2. 不等于(!=)比较特殊 除主键索引或索引是整数类型外的其它索引都失效

    EXPLAIN SELECT *
            FROM t_user
            WHERE username != 'OlUldQDIVV';
    -- 索引有效
    EXPLAIN SELECT * FROM t_user WHERE uid != 1;
    
  3. like以通配符开头(‘%’),如果非要用使用全文索引

  4. 如果条件中有or,即使其中有条件带索引也不会使用 如果想使用or,又想让索引生效,只能将or条件中的每个列都加上索引

  5. 小于 大于这个根据实际查询数据来判断,如果全盘扫描速度比索引速度要快则不走索引

  6. 索引列上不要使用函数,oracle必须使用函数索引

    -- 索引失效
    SELECT * FROM t_user WHERE substr(username ,1 ,3 ) = 'ABC' 
    
    

总结一句话就是, 使用explain 关键执行一下 key是否有值, 有值就说明走了索引,null就表示索引失效

七、key和index区别

1、说明

key 是数据库的物理结构,它包含两层意义,一是约束(偏重于约束和规范数据库的结构完整性),二是索引(辅助查询用的)。包括primary key, unique key, foreign key

2、primary key

  1. 一是约束作用(constraint),用来规范一个存储主键和唯一性,
  2. 同时也在此key上建立了一个index

3、 unique key

  1. 约束作用(constraint),规范数据的唯一性
  2. 在这个key上建立了一个index

4、foreign key

  1. 约束作用(constraint),规范数据的引用完整性
  2. 在这个key上建立了一个index

七、总结

  1. 能用唯一索引,一定用唯一索引
  2. 可以给字段加非空约束就尽量加上非空约束
  3. 联合索引的顺序不同,影响索引的选择,尽量将值少的放在前面
  4. 千万不要给大字段加索引

八 、其它

1、查看索引

  1. 语法

    show index from tblname;
    -- 或者
    show keys from tblname;
    
  2. 说明

    • Non_unique:如果索引不能包括重复词,则为0。如果可以,则为1
    • Key_name:索引的名称
    • Column_name:索引列名称
    • Index_type :索引类型
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。