22、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. 搜索语法规则

    • +一定要有(不含有该关键词的数据条均被忽略)。
    • - 不可以有(排除指定关键词,含有该关键词的均被忽略)。
    • > 提高该条匹配数据的权重值
    • * 全匹配,不像其他语法放在前面,这个要接在字符串后面。
  5. 检索模式

    • 自然语言检索: IN NATURAL LANGUAGE MODE
    • 布尔检索: IN BOOLEAN MODE
      特点如下
      • 不剔除50%以上符合的row。

      • 不自动以相关性反向排序。

      • 可以对没有FULLTEXT index的字段进行搜寻,但会非常慢。

      • 限制最长与最短的字符串。

      • 套用Stopwords。

  6. 示例代码

    -- 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')
     -- 查询必须包含ab开头的词
    SELECT * FROM articles WHERE MATCH (detail) AGAINST ('+ab*'  IN BOOLEAN MODE);   
    

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组合也可以,但实际上只用到了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. 唯一的记录添加唯一索引
  5. 频繁更新的列不要建索引
  6. 不要对索引列运算
  7. 同样过滤效果下,保持索引长度最小
  8. 合理利用组合索引,注意索引字段先后顺序
  9. 多列组合索引,过滤性高的字段最前
  10. order by 字段建立索引,
  11. 组合索引,不同的排序顺序不能使用索引

十、其它

1、查看索引

  1. 语法
    show index from tblname;
    -- 或者
    show keys from tblname;
    
  2. 说明
    • Non_unique:如果索引不能包括重复词,则为0。如果可以,则为1
    • Key_name:索引的名称
    • Column_name:索引列名称
    • Index_type :索引类型

2、执行计划(explain)

  1. 概要
    在 select 语句之前增加 explain 关键字,MySQL 会在查询上设置一个标记,执行查询时,会返回执行计划的信息,而不是执行这条SQL(如果 from 中包含子查询,仍会执行该子查询,将结果放入临时表中)


    image
  2. 主要字段说明
    • type
      system > const > eq_ref > ref > range > index > all
      一般来说,得保证查询至少达到range级别,最好能达到ref。
      index all 性能差需要优化 至少要达到 range 级别,要求是 ref 级别,如果可以是 consts 最好
    • possible_keys
      显示可能应用在这张表中的索引,一个或多个。查询涉及到的字段上若存在索引,则该索引将被列出,但不一定被查询实际使用
    • key
      实际使用的索引,如果为NULL,则没有使用索引
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,616评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,020评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,078评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,040评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,154评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,265评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,298评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,072评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,491评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,795评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,970评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,654评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,272评论 3 318
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,985评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,223评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,815评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,852评论 2 351

推荐阅读更多精彩内容

  • 一、MySQL优化 MySQL优化从哪些方面入手: (1)存储层(数据) 构建良好的数据结构。可以大大的提升我们S...
    宠辱不惊丶岁月静好阅读 2,422评论 1 8
  • 今天看到一位朋友写的mysql笔记总结,觉得写的很详细很用心,这里转载一下,供大家参考下,也希望大家能关注他原文地...
    信仰与初衷阅读 4,727评论 0 30
  • 一、概要 索引就像一本书的目录。而当用户通过索引查找数据时,就好比用户通过目录查询某章节的某个知识点。这样就帮助用...
    唯老阅读 460评论 0 1
  • 索引 数据库中的查询操作非常普遍,索引就是提升查找速度的一种手段 索引的类型 从数据结构角度分 1.B+索引:传统...
    一凡呀阅读 2,886评论 0 8
  • 手动不易,转发请注明出处 --Trance 数据库系统命令: (1).查看存储过程状态:show pro...
    Trance_b54c阅读 1,657评论 0 8