zoukankan      html  css  js  c++  java
  • MySQL索引

    一、简述

    MySQL索引的建立对于MySQL的高效运行是很重要的,索引可以大大提高MySQL的检索速度。

    打个比方,如果合理的设计且使用索引的MySQL是一辆兰博基尼的话,那么没有设计和使用索引的MySQL就是一个人力三轮车。

    拿汉语字典的目录页(索引)打比方,我们可以按拼音、笔画、偏旁部首等排序的目录(索引)快速查找到需要的字。

    索引分单列索引和组合索引。单列索引,即一个索引只包含单个列,一个表可以有多个单列索引,但这不是组合索引。组合索引,即一个索引包含多个列。

    创建索引时,你需要确保该索引是应用在 SQL 查询语句的条件(一般作为 WHERE 子句的条件)。

    实际上,索引也是一张表,该表保存了主键与索引字段,并指向实体表的记录。

    上面都在说使用索引的好处,但过多的使用索引将会造成滥用。因此索引也会有它的缺点:虽然索引大大提高了查询速度,同时却会降低更新表的速度,如对表进行INSERT、UPDATE和DELETE。因为更新表时,MySQL不仅要保存数据,还要保存一下索引文件。

    建立索引会占用磁盘空间的索引文件。

    二、索引类型

    1、普通索引

    创建索引

    CREATE INDEX IndexName ON `TableName`(`字段名`);

    如果是CHAR,VARCHAR类型,length可以小于字段实际长度;如果是BLOB和TEXT类型,必须指定 length。

    修改表结构(添加索引)

    ALTER table tableName ADD INDEX indexName('字段名')

    创建表的时候直接指定

    CREATE TABLE mytable(  
     
    ID INT NOT NULL,   
     
    username VARCHAR(16) NOT NULL,  
     
    INDEX [indexName] (username(length))  
     
    );

    删除索引的语法

    DROP INDEX [indexName] ON mytable; 

    2、唯一索引

    它与前面的普通索引类似,不同的就是:索引列的值必须唯一,但允许有空值。如果是组合索引,则列值的组合必须唯一。它有以下几种创建方式:

    创建索引

    CREATE UNIQUE INDEX indexName ON mytable(username(length))

    修改表结构

    ALTER table mytable ADD UNIQUE [indexName] (username(length))

    创建表的时候直接指定

    CREATE TABLE mytable(  
     
    ID INT NOT NULL,   
     
    username VARCHAR(16) NOT NULL,  
     
    UNIQUE [indexName] (username(length))  
     
    );

    3、主键索引

    主键索引是一种特殊的唯一索引,一个表只能有一个主键,不允许有空值(在 B+Tree 中的 InnoDB 引擎中,主键索引起到了至关重要的作用)。主键索引建立的规则是 int 优于 varchar,一般在建表的时候创建,最好是与表的其他字段不相关的列或者是业务不相关的列。一般会设为 int 而且是 AUTO_INCREMENT 自增类型的。一般是在建表的时候同时创建主键索引:

    创建表时添加

    CREATE TABLE `news` (
        `id` int(11) NOT NULL AUTO_INCREMENT ,
        `title` varchar(255)  NOT NULL ,
        `content` varchar(255)  NULL ,
        `time` varchar(20) NULL DEFAULT NULL ,
        PRIMARY KEY (`id`)
    )

    创建表后添加

    alter table tbl_name add primary key(col_name);

    4、组合索引

    一个表中含有多个单例索引不代表是组合索引,通俗一点讲,组合索引是:包含多个字段但是只有索引名称。

    CREATE INDEX id_loanNo_custNo_Index ON `award`(`id`, `loan_no`, `cust_no`);

    如果你建立了组合索引 (id_loanNo_custNo_Index),那么它实际包含的是 3 个索引 (id) (id,loan_no)(id,loan_no,cust_no)

    在使用查询的时候遵循 mysql 组合索引的 “最左前缀”,即索引 where 时的条件要按照建立索引的时候字段的排列方式。

    组合索引失效的情况。

    1、不按索引最左列开始查询(多列索引) 例如:

    index(‘c1’, ‘c2’, ‘c3’) 
    where c2 = 'aaa' # 不使用索引
    where c2 = 'aaa' and c3='sss' # 不能使用索引

    2、查询某个列有范围查询,则其右边的所有列都无法使用查询(多列查询)

    Where c1= 'xxx' and c2 like 'aa%' and c3='sss'
    # 该查询只会使用索引中的前两列,因为like是范围查询

    3、不能跳过某个字段来进行查询,这样利用不到索引,比如:

    EXPLAIN SELECT * FROM `award` WHERE id > 'rSUQFzpkDz3R' AND loan_no= 'DYxJoqZq2rd7' AND cust_no= '1449567822'; 
    因为我的索引是 (id, loan_no, cust_no),如果第一个字段出现 范围符号 的查找,那么将不会用到索引,如果我是第二个或者第三个字段使用范围符号的查找,那么它会利用索引,利用的索引是 (id),因为上面说了建立组合索引 (id, loan_no, cust_no),会出现三个索引。
    注:使用组合检索的时候可能需要把前面创建的单例检索删除,否则可能会使用单例检索

    5、全文索引

    文本字段上(text)如果建立的是普通索引,那么只有对文本的字段内容前面的字符进行索引,其字符大小根据索引建立索引时声明的大小来规定。用于搜索很长一篇文章的时候效果最好。

    如果文本中出现多个一样的字符,而且需要查找的话,那么其条件只能是 where column like '%xxxx%', 这样做会让索引失效

    这个时候全文索引就有作用了

    ALTER TABLE TableName ADD FULLTEXT(column1, column2);
    ALTER TABLE `award` ADD FULLTEXT(`message`);

    有了全文索引,就可以用 SELECT 查询命令去检索那些包含着一个或多个给定单词的数据记录了。

    SELECT * FROM TableName WHERE MATCH(column1, column2) AGAINST('xxx', 'sss', 'ddd');
    EXPLAIN SELECT * FROM `award` WHERE MATCH(message) AGAINST('aaa');

    上述命令将把 column1 和 column2 字段里有 xxx、sss、和 ddd 的数据记录全部查询出来。

    三、索引删除

    查询索引

    show index from tableName;

    删除索引

    drop index indexName on tableName;

    四、使用索引的优缺点

    优点:

    1)可以通过建立唯一索引或者主键索引,保证数据库表中每一行数据的唯一性

    2)建立索引可以大大提高检索的数据,以及减少表的检索行数

    3)在表连接的连接条件,可以加速表与表直接的相连

    4)在分组和排序字句进行数据检索,可以减少查询时间中 分组 和 排序 所消耗的时间(数据库的记录会重新排序)

    5)建立索引,在查询中使用索引,可以提高性能

    缺点:

    1)创建索引和维护索引会消耗时间,随着数据量的增加而增加

    2)索引文件会占用物理空间,除了数据表需要占用物理空间之外,每一个索引还会占用一定的物理空间

    3)当对表的数据进行 INSERT,UPDATE,DELETE 的时候,索引也要动态的维护,这样就会降低数据的维护速度,(建立索引会占用磁盘空间的索引文件。一般情况这个问题不太严重,但如果你在一个大表上创建了多种组合索引,索引文件的会膨胀很快)。

    索引只是提高效率的一个因素,如果你的MySQL有大数据量的表,就需要花时间研究建立最优秀的索引,或优化查询语句。

    因此应该只为最经常查询和最经常排序的数据列建立索引。

    MySQL里同一个数据表里的索引总数限制为16个。

    五、索引失效的场景

    1、like 以%开头,索引无效;当like前缀没有%,后缀有%时,索引有效。

    2、or语句前后没有同时使用索引。当or左右查询字段只有一个是索引,该索引失效,只有当or左右查询字段均为索引时,才会生效。

    3、组合索引,不是使用第一列索引,索引失效。

    4、数据类型出现隐式转化。如varchar不加单引号的话可能会自动转换为int型,使索引无效,产生全表扫描。

    5、在索引字段上使用not,<>,!=。不等于操作符是永远不会用到索引的,因此对它的处理只会产生全表扫描。 优化方法: key<>0 改为 key>0 or key<0。

    6、对索引字段进行计算操作、字段上使用函数。(索引为 emp(ename,empno,sal))。

    7、当全表扫描速度比索引速度快时,mysql会使用全表扫描,此时索引失效。

    索引失效分析工具:

    可以使用explain命令加在要分析的sql语句前面,在执行结果中查看key这一列的值,如果为NULL,说明没有使用索引。

  • 相关阅读:
    java谜题
    Can't connect to local MySQL server through socket '/var/lib/mysql/mysql.sock' 的解决办
    考虑用静态工厂代替构造器
    Can't connect to local MySQL server through socket '/var/lib/mysql/mysql.sock' 的解决办
    100 个高质量的 XHTML/CSS 模板(上)
    登陆时的安全性
    Flex 开发架构(五): Mate-基于标签的框架
    NIO的基本概念及简单示例
    Flex与jsp的联系
    福布斯:Sun的六大失误
  • 原文地址:https://www.cnblogs.com/wmy666/p/13903302.html
Copyright © 2011-2022 走看看