zoukankan      html  css  js  c++  java
  • MYSQL复习笔记7-索引

    Date: 20140207
    Auth: Jin

    索引是根据表中一列或若干列按照一定顺序建立的列值与记录行之间的对应关系表。

    索引的主要作用

    • 快速存取数据
    • 保证数据记录的唯一性
    • 实现表与表之间的参照完整性
    • 在使用ORDER BY,GROUP BY子句进行数据检索时,利用索引可以减少排序和分组的时间。

    一、索引结构 Index_type
    包括B-Tree,Hash,full-text,R-Tree
    1、B-Tree 除Archive存储引擎外其他存储引擎都支持,使用最频繁
    2、Hash Memory和NDB Cluster支持,使用较少
    3、Full-text 全文索引 仅MyISAM存储引擎支持,且仅有char,varchar,text这三种数据类型的列支持才可以建全文索引
    4、R-Tree 解决空间数据检索的问题 使用少

    btree索引和hash索引的区别
    http://www.cnblogs.com/vicenteforever/articles/1789613.html

    二、索引类型
    1、UNIQUE KEY 唯一索引
    索引列的值必须唯一,但允许有空值。如果是组合索引(可以多个字段组合),则列值的组合必须唯一。一个表可以有多个唯一索引。
    可设置索引名

    2、PRIMARY KEY 主键索引
    一个表只能有一个主键索引,索引字段不能为空,一种特殊的唯一索引。
    索引名只能是

    3、普通索引
    最基本的索引,它没有任何限制
    可设置索引名

    4、联合索引(组合索引)
    多个字段联合组成的普通索引
    可设置索引名

    三、查看表的索引
    1、语句
    mysql> show index from table_name;
    mysql> show keys from table_name;

    mysql> show index from Product;
    +-----------+------------+--------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
    | Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment |
    +-----------+------------+--------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
    | Product | 0 | PRIMARY | 1 | productId | A | 0 | NULL | NULL | | BTREE | |
    | Product | 0 | index_UNIQUE | 1 | pname | A | 0 | NULL | NULL | | BTREE | |
    | Product | 0 | index_UNIQUE_union | 1 | productId | A | 0 | NULL | NULL | | BTREE | |
    | Product | 0 | index_UNIQUE_union | 2 | productName | A | 0 | 5 | NULL | | BTREE | |
    | Product | 1 | index_price | 1 | price | A | 0 | NULL | NULL | YES | BTREE | |
    | Product | 1 | index_union | 1 | productId | A | 0 | NULL | NULL | | BTREE | |
    | Product | 1 | index_union | 2 | pname | A | 0 | NULL | NULL | | BTREE | |
    | Product | 1 | index_productName | 1 | productName | A | 0 | 10 | NULL | | BTREE | |
    +-----------+------------+--------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
    8 rows in set (0.00 sec

    2、说明
    · Table
    表的名称。
    · Non_unique
    如果MySQL索引不能包括重复词,则为0。如果可以,则为1。
    · Key_name
    索引的名称。
    · Seq_in_index #普通索引才可以指定列名称
    索引中的列序列号,从1开始。
    · Column_name
    列名称。
    · Collation
    列以什么方式存储在索引中。在MySQL中,有值‘A’(升序)或NULL(无分类)。
    · Cardinality
    MySQL索引中唯一值的数目的估计值。通过运行ANALYZE TABLE或myisamchk -a可以更新。基数根据被存储为整数的统计数据来计数,所以即使对于小型表,该值也没有必要是精确的。基数越
    大,当进行联合时,MySQL使用该索引的机会就越大。
    · Sub_part
    如果列只是被部分地编入索引,则为被编入索引的字符的数目。如果整列被编入索引,则为NULL。
    · Packed
    指示关键字如何被压缩。如果没有被压缩,则为NULL。
    · Null
    如果列含有NULL,则含有YES。如果没有,则该列含有NO。
    · Index_type
    用过的索引方法(BTREE, FULLTEXT, HASH, RTREE)。
    · Comment

    三、创建索引和删除
    创建表时创建索引对全部索引都有有效
    CREATE TABLE `Product19` (
    `productId` int(6) NOT NULL AUTO_INCREMENT,
    `pname` varchar(25) NOT NULL,
    `productName` varchar(25) NOT NULL,
    `created` date DEFAULT '2000-01-01',
    `price` int(11) DEFAULT '200',
    PRIMARY KEY (`productId`),
    UNIQUE KEY `index_UNIQUE` (`pname`),
    UNIQUE KEY `index_UNIQUE_union` (`productId`,`productName`(5)),
    KEY `index_price` (`price`),
    KEY `index_union` (`productId`,`pname`),
    KEY `index_productName` (`productName`(10))
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

    按索引类型分区
    (一)UNIQUE KEY 唯一索引
    1、添加索引
    1)、创建表时创建
    create table Product(
    productName varchar(25) NOT NULL,
    UNIQUE KEY `unique_productName`(productName)
    )ENGINE=InnoDB DEFAULT CHARSET=utf8;

    2)、修改表-添加新字段为表的唯一索引
    alter table Product add productName varchar(25) UNIQUE;

    3)、修改表-修改已存在的字段为唯一索引
    单字段作为唯一索引
    mysql> alter table Product add UNIQUE KEY `unique_pname`(pname);
    单个字段的部分字符串作为唯一索引
    alter table Product add UNIQUE KEY `unique_pname2`(pname(10));
    多个字段联合组成的唯一索引
    mysql> alter table Product add UNIQUE KEY `unique_union`(productName,productId);

    4)、create index方式添加
    也需添加的字段已经存在
    CREATE UNIQUE INDEX indexName ON mytable(username(length))
    单字段作为唯一索引
    mysql> create UNIQUE INDEX `unique_productName` on Product(productName);
    单个字段的部分字符串作为唯一索引
    mysql> create UNIQUE INDEX `unique_productName1` on Product(productName(5));
    多个字段联合组成的唯一索引
    mysql> create UNIQUE INDEX `unique_union` on Product(productName,productId);

    注意:不管一个字段的部分,还是多个字段组合都必须是唯一的


    最好还是创建表时候一起创建,因为键值重复的问题。
    mysql> alter table Product add productName varchar(25) NOT NULL UNIQUE;
    ERROR 1062 (23000): Duplicate entry '' for key 'productName'

    2、删除索引
    删除索引和删除普通索引一样
    1)修改表drop
    mysql> alter table Product drop index unique_pname;
    2)DROP INDEX ON table
    DROP INDEX [indexName] ON mytable;
    mysql> drop index `unique_union` ON Product;

    (二)PRIMARY KEY 主键索引
    1、添加索引
    1)、创建表时创建
    create table Product(
    productId int(6) NOT NULL AUTO_INCREMENT,
    PRIMARY KEY(productId)
    )ENGINE=InnoDB DEFAULT CHARSET=utf8;

    2)、修改表-添加新字段为表的主键索引
    mysql> alter table Product add productId int(6) NOT NULL PRIMARY KEY;

    3)修改表-修改已存在的字段为主键索引
    mysql> alter table Product add PRIMARY KEY(productId);

    注意:
    * CREATE INDEX 无法用在PRIMARY KEY

    2、删除索引
    修改表drop PRIMARY KEY
    mysql> alter table tb1 drop PRIMARY KEY;
    注意
    * 如果主键索引列是自增无法drop
    mysql> alter table Product drop PRIMARY KEY;
    ERROR 1075 (42000): Incorrect table definition; there can be only one auto column and it must be defined as a key

    * DROP INDEX 无法用在PRIMARY KEY

    (三)普通索引
    1、添加索引
    1)、创建表时创建
    create table Product(
    productName varchar(25) NOT NULL,
    KEY `index_productName`(productName)
    )ENGINE=InnoDB DEFAULT CHARSET=utf8;

    2)、修改表-修改已存在的字段为唯一索引
    单字段作为唯一索引
    mysql> alter table Product add index `index_productName`(productName);
    单个字段的部分字符串作为唯一索引
    mysql> alter table Product add index `index_productName`(productName(10));

    3)、create index方式添加
    也需添加的字段已经存在
    CREATE INDEX indexName ON mytable(username(length))
    单字段作为唯一索引
    mysql> create INDEX `index_productName` on Product(productName);
    单个字段的部分字符串作为唯一索引
    mysql> create INDEX `index_productName` on Product(productName(10));
    mysql> create INDEX `index_productName` on Product11(productName) USING HASH;

    注意:无法在修改表-添加新字段为表的唯一索引

    2、删除索引
    删除索引和删除普通索引一样
    1)修改表drop
    mysql> alter table Product drop index index_productName;

    2)DROP INDEX ON table
    DROP INDEX [indexName] ON mytable;
    mysql> drop index `index_productName` ON Product

    (三)联合索引
    联合索引就是多个字段组成的普通索引
    1、添加索引
    1)、创建表时创建
    create table Product(
    productId int(6) NOT NULL,
    productName varchar(25) NOT NULL,
    KEY `union_index;`(productId,productName)
    )ENGINE=InnoDB DEFAULT CHARSET=utf8;

    2)、修改表-修改已存在的字段为唯一索引
    mysql> alter table Product add index union_index(productId,productName);

    3)、create index方式添加
    也需添加的字段已经存在
    CREATE INDEX indexName ON mytable(username(length))
    mysql> create index union_index ON Product(productId,productName);
    mysql> create index union_index ON Product(productId,productName(10));

    2、删除索引
    删除索引和删除普通索引一样
    1)修改表drop
    mysql> alter table Product13 drop index union_index;

    2)DROP INDEX ON table
    DROP INDEX [indexName] ON mytable;
    mysql> drop index union_index on Product;

    总结:
    1、所有的索引都可以在创建表的时候添加以及修改表(字段已存在)添加
    2、修改表-添加新字段为表的索引,只能用于PRIMARY KEY和UNIQUE(不推荐)
    3、PRIMARY KEY和UNIQUE KEY最好创建表时候添加(推荐)
    4、CREATE INDEX/DROP INDEX,以及alter table TABLENAME drop index只能用于普通索引和UNIQUE,无法用于PRIMARY KEY
    5、含有AUTO_INCREMENT且已经有数据的PRIMARY KEY无法删除
    6、QUNIUE KEY 注意:不管一个字段的部分,一个字段,还是多个字段组合都必须是唯一的


    四、建立索引的时机
    需要在什么情况下建立索引呢?
    一般来说,在WHERE和JOIN中出现的列需要建立索引,但也不完全如此,因为MySQL只对<,<=,=,>,>=,BETWEEN,IN,以及某些时候的LIKE才会使用索引。例如:
    SELECT a.Name FROM gameusers a LEFT JOIN bbsusers b ON a.Name=b.username WHERE a.age=20 AND a.city='上海'
    此时就需要对city和age建立索引,由于mytable表的userame也出现在了JOIN子句中,也有对它建立索引的必要。

    刚才提到只有某些时候的LIKE才需建立索引。因为在以通配符%和_开头作查询时,MySQL不会使用索引。例如下句会使用索引:
    SELECT * FROM bbsusers WHERE username like'admin%'
    而下句就不会使用:
    SELECT * FROM mytable WHEREt Name like'%admin'
    因此,在使用LIKE时应注意以上的区别。

    五、索引的不足之处和使用索引的注意事项
    1、索引的不足之处
    上面都在说使用索引的好处,但过多的使用索引将会造成滥用。因此索引也会有它的缺点:

    1)虽然索引大大提高了查询速度,同时却会降低更新表的速度,如对表进行INSERT、UPDATE和DELETE。因为更新表时,MySQL不仅要保存数据,还要保存一下索引文件。

    2)建立索引会占用磁盘空间的索引文件。一般情况这个问题不太严重,但如果你在一个大表上创建了多种组合索引,索引文件的会膨胀很快。

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

    2、使用索引的注意事项
    使用索引时,有以下一些技巧和注意事项:

    1)索引不会包含有NULL值的列
    只要列中包含有NULL值都将不会被包含在索引中,复合索引中只要有一列含有NULL值,那么这一列对于此复合索引就是无效的。所以我们在数据库设计时不要让字段的默认值为NULL。

    2)使用短索引
    对串列进行索引,如果可能应该指定一个前缀长度。例如,如果有一个CHAR(255)的列,如果在前10个或20个字符内,多数值是惟一的,那么就不要对整个列进行索引。短索引不仅可以提高查
    询速度而且可以节省磁盘空间和I/O操作。

    3)索引列排序
    MySQL查询只使用一个索引,因此如果where子句中已经使用了索引的话,那么order by中的列是不会使用索引的。因此数据库默认排序可以符合要求的情况下不要使用排序操作;尽量不要包
    含多个列的排序,如果需要最好给这些列创建复合索引。

    4)like语句操作
    一般情况下不鼓励使用like操作,如果非使用不可,如何使用也是一个问题。like “%aaa%” 不会使用索引而like “aaa%”可以使用索引。

    5)不要在列上进行运算
    select * from users where YEAR(adddate)<2007;
    将在每个行上进行运算,这将导致索引失效而进行全表扫描,因此我们可以改成
    select * from users where adddate<‘2007-01-01’;

    6)不使用NOT IN和<>操作

  • 相关阅读:
    Codeforces.468C.Hack it!(构造)
    BZOJ.3227.[SDOI2008]红黑树tree(树形DP 思路)
    146
    145
    144
    143
    142
    141
    140
    139
  • 原文地址:https://www.cnblogs.com/diege/p/3540006.html
Copyright © 2011-2022 走看看