系列文章目录
MySQL(一)——索引底层数据结构与算法
MySQL(二)——Explain详情与索引最佳实践
MySQL(三)——MySQL的内部组件结构及bin-log归档
MySQL(四)——MySQL索引优化实战
MySQL(五)——MySQL索引优化实战(多表联查优化)
MySQL(六)——深入理解MySQL事务隔离级别与锁机制
MySQL(七)——深入理解MVCC与BufferPool缓存机制
Explain详情与索引最佳实践
MySQL的索引
使用索引是为了加快查询数据库表数据的速度。
索引是在存储引擎中实现的,也就是说不同的存储引擎,会使用不同的索引
MyISAM和InnoDB存储引擎:只支持BTREE索引
MEMORY/HEAP存储引擎:支持HASH和BTREE索引
索引分类
单列索引(普通索引,唯一索引,主键索引)
一个索引只包含单个列,但一个表中可以有多个单列索引。
普通索引:允许索引列中有重复值和空值
唯一索引:不允许重复,但是允许为空值,
主键索引:不允许重复和空值
索引的创建
CREATE TABLE book (
bookid INT NOT NULL,
bookname VARCHAR (255) NOT NULL,
AUTHORS VARCHAR (255) NOT NULL,
info VARCHAR (255) NULL,
COMMENT VARCHAR (255) NULL,
year_publication YEAR NOT NULL,
INDEX (year_publication)
);
CREATE TABLE book1 (
bookid INT NOT NULL,
bookname VARCHAR (255) NOT NULL,
AUTHORS VARCHAR (255) NOT NULL,
info VARCHAR (255) NULL,
COMMENT VARCHAR (255) NULL,
year_publication YEAR NOT NULL,
KEY (year_publication)
);
EXPLAIN SELECT * FROM book WHERE year_publication = 1990;
项目 | 介绍 |
---|---|
id: | SELECT识别符。这是SELECT的查询序列号,也就是一条语句中,该select是第几次出现。在此语句中,select就只有一个,所以是1. |
select_type: | 所使用的SELECT查询类型,SIMPLE表示为简单的SELECT,不实用UNION或子查询,就为简单的SELECT。也就是说在该SELECT查询时会使用索引。其他取值,PRIMARY:最外面的SELECT.在拥有子查询时,就会出现两个以上的SELECT。UNION:union(两张表连接)中的第二个或后面的select语句 SUBQUERY:在子查询中,第二SELECT。 |
table: | 数据表的名字。他们按被读取的先后顺序排列,这里因为只查询一张表,所以只显示book |
type: | 指定本数据表和其他数据表之间的关联关系,该表中所有符合检索值的记录都会被取出来和从上一个表中取出来的记录作联合。ref用于连接程序使用键的最左前缀或者是该键不是 primary key 或 unique索引(换句话说,就是连接程序无法根据键值只取得一条记录)的情况。当根据键值只查询到少数几条匹配的记录时,这就是一个不错的连接类型。可能的取值有 system、const、eq_ref、index和All |
possible_keys: | MySQL在搜索数据记录时可以选用的各个索引,该表中就只有一个索引,year_publication |
key: | 实际选用的索引 |
key_len: | 显示了mysql使用索引的长度(也就是使用的索引个数),当 key 字段的值为 null时,索引的长度就是 null。注意,key_len的值可以告诉你在联合索引中mysql会真正使用了哪些索引。这里就使用了1个索引,所以为1, |
ref: | 给出关联关系中另一个数据表中数据列的名字。常量(const),这里使用的是1990,就是常量。 |
rows: | MySQL在执行这个查询时预计会从这个数据表里读出的数据行的个数。 |
extra: | 提供了与关联操作有关的信息,没有则什么都不写。 |
我们最主要的是看possible_keys和key 这两个属性,上面显示了key为year_publication。说明使用了索引。
创建唯一索引
CREATE TABLE t1 (
id INT NOT NULL,
NAME CHAR (30) NOT NULL,
UNIQUE INDEX UniqIdx (id)
);
SHOW CREATE TABLE t1
INSERT INTO t1 VALUES(1,'xxx');
EXPLAIN SELECT * FROM t1 WHERE id = 1
EXPLAIN SELECT * FROM t1 WHERE id = 5
创建主键索引
CREATE TABLE t2 (
id INT NOT NULL,
NAME CHAR (10),
PRIMARY KEY (id)
);
INSERT INTO t2 VALUES(1,'QQQ');
EXPLAIN SELECT * FROM t2 WHERE id = 1
组合索引
在表中的多个字段组合上创建的索引,只有在查询条件中使用了这些字段的左边字段时,索引才会被使用,使用组合索引时遵循最左前缀集合。
创建一个表t3,在表中的id、name和age字段上建立组合索引
CREATE TABLE t3 (
id INT NOT NULL,
NAME CHAR (30) NOT NULL,
age INT NOT NULL,
info VARCHAR (255),
INDEX MultiIdx (id, NAME, age)
);
解释最左前缀
组合索引就是遵从了最左前缀,利用索引中最左边的列集来匹配行,这样的列集称为最左前缀,例如,这里由id、name和age3个字段构成的索引,索引行中就按id/name/age的顺序存放,索引可以索引下面字段组合(id,name,age)、(id,name)或者(id)。如果要查询的字段不构成索引最左面的前缀,那么就不会使用索引,比如,age或者(name,age)组合就不会使用索引查询。
EXPLAIN SELECT * FROM t3 WHERE age = 3 AND name = 'bob'
全文索引
全文索引,只有在MyISAM引擎上才能使用,只能在CHAR,VARCHAR,TEXT类型字段上使用全文索引。索引总是对整个列进行,不支持前缀索引,
就是在一堆文字中,通过其中的某个关键字等,就能找到该字段所属的记录行
CREATE TABLE t4 (
id INT NOT NULL,
NAME CHAR (30) NOT NULL,
age INT NOT NULL,
info VARCHAR (255),
FULLTEXT INDEX FullTxtIdx (info)
) ENGINE = MyISAM;
SHOW CREATE TABLE t4
INSERT INTO t4 VALUES(8,'AAA',3,'text is so good,hei,my name is bob'),(9,'BBB',4,'my name is gorlr');
SELECT * FROM t4 WHERE MATCH(info) AGAINST('name' IN BOOLEAN MODE);
EXPLAIN SELECT * FROM t4 WHERE MATCH(info) AGAINST('gorlr');
show variables like 'ft%'
repair table t4 quick
空间索引
空间索引是对空间数据类型的字段建立的索引,MySQL中的空间数据类型有四种,GEOMETRY、POINT、LINESTRING、POLYGON。
在创建空间索引时,使用SPATIAL关键字。
要求,引擎为MyISAM,创建空间索引的列,必须将其声明为NOT NULL。
CREATE TABLE t5 (
g GEOMETRY NOT NULL,
SPATIAL INDEX spatIdx (g)
) ENGINE = MyISAM;
SHOW CREATE TABLE t5
在已经存在的表上创建索引
ALTER TABLE 表名 ADD[UNIQUE|FULLTEXT|SPATIAL] [INDEX|KEY] [索引名] (索引字段名)[ASC|DESC]
查看表中创建的索引
SHOW INDEX FROM book
字段 | 内容 |
---|---|
Table: | 创建索引的表 |
Non_unique: | 表示索引非唯一,1代表 非唯一索引, 0代表 唯一索引,意思就是该索引是不是唯一索引 |
Key_name: | 索引名称 |
Seq_in_index | 表示该字段在索引中的位置,单列索引的话该值为1,组合索引为每个字段在索引定义中的顺序(这个只需要知道单列索引该值就为1,组合索引为别的) |
Column_name: | 表示定义索引的列字段 |
Sub_part: | 表示索引的长度 |
Null: | 表示该字段是否能为空值 |
Index_type: | 表示索引类型 |
ALTER TABLE book ADD INDEX BkNameIdx(bookname(30));
使用CREATE INDEX创建索引。
CREATE [UNIQUE|FULLTEXT|SPATIAL] [INDEX|KEY] 索引名称 ON 表名(创建索引的字段名[length])
CREATE INDEX BkBookNameIdx ON book(bookname);
删除索引
格式一:ALTER TABLE 表名 DROP INDEX 索引名。
ALTER TABLE book DROP INDEX BkBookNameIdx;
格式二:DROP INDEX 索引名 ON 表名;
DROP INDEX BkNameIdx ON book;