MySQL索引

作者: InnocenceYWQ | 来源:发表于2018-10-09 16:48 被阅读9次

    什么是索引

    我们需要知道索引其实是一种数据结构,其功能是帮助我们快速匹配查找到需要的数据行,是数据库性能优化最常用的工具之一。其作用相当于超市里的导购员、书本里的目录。


    索引类型

    主键索引:
    主键是一种唯一性索引,但它必须指定为PRIMARY KEY,每个表只能有一个主键。

    alert table tablename add primary key (字段名)

    唯一索引:
    索引列的所有值都只能出现一次,即必须唯一,值可以为空。

    alter table table_name add primary key (字段名);

    普通索引 :
    基本的索引类型,值可以为空,没有唯一性的限制。

    alter table table_name add index (字段名);

    全文索引:
    全文索引的索引类型为FULLTEXT。全文索引可以在varchar、char、text类型的列上创建。可以通过ALTER TABLE或CREATE INDEX命令创建。对于大规模的数据集,通过ALTER TABLE(或者CREATE INDEX)命令创建全文索引要比把记录插入带有全文索引的空表更快。MyISAM支持全文索引,InnoDB在mysql5.6之后支持了全文索引。

    alter table 表名 add FULLTEXT(字段名);


    查看表的所有索引和删除

     #查看:
    show indexes from `表名`;
    或
    show keys from `表名`;
    #删除
    alter table `表名` drop index 索引名;
    

    索引的机制

    1.为什么我们添加完索引后查询速度为变快?

    • 传统的查询方法,是按照表的顺序遍历的,不论查询几条数据,mysql需要将表的数据从头到尾遍历一遍
    • 在我们添加完索引之后,mysql一般通过BTREE算法生成一个索引文件,在查询数据库时,找到索引文件进行遍历(折半查找大幅查询效率),找到相应的键从而获取数据

    2.索引的代价

    • 创建索引是为产生索引文件的,占用磁盘空间
    • 索引文件是一个二叉树类型的文件,可想而知我们的dml操作同样也会对索引文件进行修改,所以性能会下降

    3.在哪些column上使用索引?

    • 较频繁的作为查询条件字段应该创建索引
    • 唯一性太差的字段不适合创建索引,尽管频繁作为查询条件,例如gender性别字段
    • 新非常频繁的字段不适合作为索引
    • 不会出现在where子句中的字段不该创建索引

    优缺点

    MySQL中索引的存储类型有两种:BTREE和HASH,具体和表的存储引擎相关;
    MyISAM和InnoDB存储引擎只支持BTREE索引,MEMORY/HEAP存储引擎可以支持HASH和BTREE索引。

    优点

    • 加快数据的查询速度
    • 唯一索引,可以保证数据库表中每一行数据的唯一性
    • 在实现数据的参考完整性方面,可以加速表和表之间的连接
    • 在使用分组和排序子句进行数据查询时,也可以显著减少查询中分组和排序的时间

    缺点

    • 占用磁盘空间,除了数据表占数据空间之外,每一个索引还要占一定的物理空间,如果有大量的索引,索引文件可能比数据文件更快达到最大文件尺寸(合理运用,问题不大)
    • 损耗性能(添加、修改、删除) 索引需要动态地维护

    注意事项

    • 索引并非越多越好,一个表中如有大量的索引,不仅占用磁盘空间,而且会影响INSERT、DELETE、UPDATE等语句的性能,因为当表中的数据更改的同时,索引也会进行调整和更新
    • 避免对经常更新的表设计过多的索引,并且索引中的列尽可能要少,而对经常用于查询的字 段应该创建索引,但要避免添加不必要的字段
    • 数据量小的表最好不要使用索引,由于数据较少,查询花费的时间可能比遍历索引时间还要短,索引可能不会产生优化效果
    • 在条件表达式中经常用到的不同值较多的列上建立索引,在不同值较少的列上不要建立索引,比如性别字段只有男和女,就没必要建立索引。如果建立索引不但不会提高查询效率,反而会严重降低更新速度
    • 当唯一性是某种数据本身的特征时,指定唯一索引。使用唯一索引需能确保定义的列的数据完整性,以提高查询速度
    • 在频繁排序或分组(即group by或order by操作)的列上建立索引,如果待排序的列有多个,可以在这些列上建立组合索引

    实例

    使用 CREATE TABLE 创建表的时候,除了可以定义列的数据类型,还可以定义主键约束、外键约束或者唯一性约束,而不论创建哪种约束,在定义约束的同时相当于在指定列上创建了一个索引。
    创建表时创建索引的基本语法如下:

    CREATE TABLE table_name[col_name data_type]
    [UNIQUE|FULLTEXT|SPATIAL]
    [INDEX|KEY]
    [index_name](col_name[length])
    [ASC|DESC]
    

    释义

    • UNIQUE、FULLTEXT和SPATIAL为可选参数,分别表示唯一索引、全文索引和空间索引
    • INDEX和KEY为同义词,二者作用相同,用来指定创建索引
    • col_name为需要创建索引的字段列,该列必须从数据表中该定义的多个列中选择
    • index_name为指定索引的名称,为可选参数,如果不指定则MySQL默认col_name为索引值
    • length为可选参数,表示索引的长度,只有字符串类型的字段才能指定索引长度
    • ASC或DESC指定升序或者降序的索引值存储

    普通索引

    -- 这句作用是,如果 customer1 存在就删除
    DROP TABLE IF EXISTS customer1;
    CREATE TABLE `customer1` (
      `customer_id` bigint(20) NOT NULL COMMENT '客户ID',
      `customer_name` varchar(30) DEFAULT NULL COMMENT '客户姓名',
      INDEX `idx_customer_id` (`customer_id`) USING BTREE
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='客户表';
    

    唯一索引
    单列索引是在数据表中的某一个字段上创建的索引,一个表中可以创建多个单列索引,前面两个例子中创建的索引都是单列索引,比如:

    DROP TABLE
    IF EXISTS customer1;
    
    CREATE TABLE `customer1` (
        `customer_id` BIGINT (20) NOT NULL COMMENT '客户ID',
        `customer_name` VARCHAR (30) DEFAULT NULL COMMENT '客户姓名',
        UNIQUE INDEX `idx_customer_id` (`customer_id`) USING BTREE
    ) ENGINE = INNODB DEFAULT CHARSET = utf8mb4 COMMENT = '客户表';
    

    这样就代表在表的customer_id字段上创建了一个名为idx_customer_id的唯一索引

    组合索引
    组合索引是在多个字段上创建一个索引,比如:

    DROP TABLE
    IF EXISTS customer1;
    
    CREATE TABLE `customer1` (
        `customer_id` BIGINT (20) NOT NULL COMMENT '客户ID',
        `customer_name` VARCHAR (30) DEFAULT NULL COMMENT '客户姓名',
         INDEX `idx_group_customer` (`customer_id`,`customer_name`) USING BTREE
    ) ENGINE = INNODB DEFAULT CHARSET = utf8mb4 COMMENT = '客户表';
    
    SHOW INDEX FROM customer1;
    

    这就为customer_id、customer_name两个字段成功创建了一个名为idx_group_customer的组合索引,通过SHOW INDEX FROM customer1; 将会看到两条记录

    全文索引
    全文索引可以对全文进行搜索,只有MyISAM存储引擎支持全文索引,并且只为CHAR、VARCHAR和TEXT列,索引总是对整个列进行,不支持局部索引,比如:

    DROP TABLE
    IF EXISTS customer1;
    
    CREATE TABLE `customer1` (
        `customer_id` BIGINT (20) NOT NULL COMMENT '客户ID',
        `customer_name` VARCHAR (255) DEFAULT NULL COMMENT '客户姓名',
         FULLTEXT INDEX `idx_fulltext_customer_name` (`customer_name`)
    ) ENGINE = MyISAM DEFAULT CHARSET = utf8mb4 COMMENT = '客户表';
    
    SHOW INDEX FROM customer1;
    

    因为默认的存储引擎为InnoDB,而全文索引只支持MyISAM,所以这里创建表的时候要手动指定一下引擎。

    看到这么创建,就在info字段上成功建立了一个名为idx_fulltext_customer_name的FULLTEXT全文索引,全文索引非常适合大型数据库,而对于小的数据集,它的用处可能比较小

    在已经存在的表上创建索引
    在已经存在的表上创建索引,可以使用ALTER TABLE语句或者CREATE INDEX语句,所以,分别讲解一下如何使用ALTER TABLE和CREATE INDEX语句在已知的表字段上创建索引。

    ALTER TABLE 语法
    ALTER TABLE创建索引的基本语法为:

    ALTER TABLE table_name ADD [UNIQUE|FUUTEXT|SPATIAL]
    [INDEX|KEY] [index_name] (col_name[length],...) [ASC|DESC]
    

    普通索引

    ALTER TABLE customer1 ADD INDEX idx_customer_id(`customer_id`);
    
    ALTER TABLE customer1 ADD INDEX idx_customer_id(customer_name(50));
    

    意思是查询的时候,只需要检索前面50个字符。这里专门提一下,对字符串类型的字段进行索引,如果可以尽可能的指定一个前缀长度,例如,一个CHAR(255)的列,如果在前10个或者前30个字符内,多数值是唯一的,则不需要对整个列进行索引,短索引不仅可以提高查询速度而且可以节省磁盘空间、减少I/O操作。

    唯一索引

    ALTER TABLE customer1 ADD UNIQUE INDEX `idx_customer_id` (`customer_id`);
    

    组合索引

    ALTER TABLE customer1 ADD INDEX `idx_group_customer` (`customer_id`,`customer_name`);
    

    删除索引
    最后一项工作就是删除索引了,可以使用ALTER TABLE和DROP INDEX删除索引。

    ALTER TABLE 语法
    ALTER TABLE的基本语法为:

    ALTER TABLE table_name DROP EXISTS index_name;
    
    ALTER TABLE table_name DROP INDEX IF EXISTS index_name;
    

    DROP INDEX 语法
    DROP INDEX的基本语法为:

    DROP INDEX index_name ON table_name
    
    DROP INDEX IF EXISTS  index_name ON table_name
    

    相关文章

      网友评论

        本文标题:MySQL索引

        本文链接:https://www.haomeiwen.com/subject/qfhyaftx.html