1.索引的分类
MySQL 的索引包括普通索引、唯一性索引、全文索引、单列索引、多列索引和空间索引等。从 功能逻辑 上说,索引主要有 4 种,分别是普通索引、唯一索引、主键索引、全文索引。按照 物理实现方式 ,索引可以分为 2 种:聚簇索引和非聚簇索引。按照 作用字段个数 进行划分,分成单列索引和联合索引。
2.创建索引的三种方式
2.1 方式一:CREATE TABLE
2.1.1 小例子
CREATE DATABASE dbtest2;
USE dbtest2;
CREATE TABLE dept (
dept_id INT PRIMARY KEY AUTO_INCREMENT,
dept_name VARCHAR(20)
);
SHOW INDEX FROM dept;
CREATE TABLE emp (
emp_id INT PRIMARY KEY AUTO_INCREMENT,
emp_name VARCHAR(20) UNIQUE,
dept_id INT,
CONSTRAINT fk_emp_dept_id FOREIGN KEY(dept_id) REFERENCES dept(dept_id)
);
SHOW INDEX FROM emp;
2.1.2 普通索引
CREATE TABLE book (
book_id INT,
book_name VARCHAR(100),
`authors` VARCHAR(100),
info VARCHAR(100),
`comment` VARCHAR(100),
year_publication YEAR,
INDEX idx_bname(book_name)
);
SHOW INDEX FROM book;
如果我们写一个简单的sql语句,在where后面用 book_name 来筛选,可以通过 explain 性能分析工具来看看是什么样的?
EXPLAIN
SELECT *
FROM book
WHERE book_name = 'mysql';
2.1.3 唯一性索引
CREATE TABLE book1 (
book_id INT,
book_name VARCHAR(100),
`authors` VARCHAR(100),
info VARCHAR(100),
`comment` VARCHAR(100),
year_publication YEAR,
UNIQUE INDEX uk_idx_cmt(`comment`)
);
SHOW INDEX FROM book1;
接下来,依次向表中插入三条记录,在插入第二条记录的时候,就会报错。而第三条记录是正常执行的。
INSERT INTO book1(book_id, book_name, `comment`)
VALUES(1, 'MySQL高级', '适合有数据库开发经验的人员学习');
INSERT INTO book1(book_id, book_name, `comment`)
VALUES(1, 'MySQL高级', '适合有数据库开发经验的人员学习');
INSERT INTO book1(book_id, book_name, `comment`)
VALUES(1, 'MySQL高级', NULL);
最终,在book1这张表中,将存在两条记录。
2.1.4 主键索引
CREATE TABLE book2 (
book_id INT PRIMARY KEY,
book_name VARCHAR(100),
`authors` VARCHAR(100),
info VARCHAR(100),
`comment` VARCHAR(100),
year_publication YEAR
);
SHOW INDEX FROM book2;
2.1.5 单列索引
其实我们上面创建的那些都是单列索引。
CREATE TABLE book3 (
book_id INT ,
book_name VARCHAR(100),
AUTHORS VARCHAR(100),
info VARCHAR(100) ,
COMMENT VARCHAR(100),
year_publication YEAR,
UNIQUE INDEX idx_bname(book_name)
);
SHOW INDEX FROM book3;
2.1.6 联合索引
CREATE TABLE book4 (
book_id INT ,
book_name VARCHAR(100),
AUTHORS VARCHAR(100),
info VARCHAR(100) ,
COMMENT VARCHAR(100),
year_publication YEAR,
INDEX mul_bid_bname_info(book_id, book_name, info)
);
SHOW INDEX FROM book4;
下面我们通过两条sql来分析一下,联合索引在查找过程中是怎么走的?
EXPLAIN
SELECT *
FROM book4
WHERE book_id = 1001 AND book_name = 'mysql';
解释:因为我们建的联合索引是 book_id, book_name, info 这样的顺序,所以在构建B+树的时候,就是先按照 book_id 来进行排序,当book_id相同时,再按照 book_name来排序,当book_name一样时,最后按照info来排序。(在B+树中,book_name实际上是位于book_id下方的,查找一定是先经过book_id、后经过book_name的)
所以上面这条sql,会先走book_id,再走book_name的。
EXPLAIN
SELECT *
FROM book4
WHERE book_name = 'mysql';
经过上面的分析,那么这条sql为什么就没有走联合索引呢?(这book_name不是存在于联合索引中吗?),这里其实还是构建B+树的顺序问题,你要想在where筛选中走book_name索引,你就必须先要走book_id索引的,因为book_name在联合索引中位于book_id之后,所以在B+树中book_name就处于book_id下方,你连B+树的第二层(假设)都还没走到,又何谈到达B+树的第三层呢? 所以这条sql是不会走索引的。
2.1.7 全文索引
CREATE TABLE test4 (
id INT NOT NULL,
NAME CHAR(30) NOT NULL,
age INT NOT NULL,
info VARCHAR(255),
FULLTEXT INDEX futxt_idx_info(info(50))
);
SHOW INDEX FROM test4;
2.2 方式二:ALTER TABLE ... ADD INDEX ...
DROP TABLE IF EXISTS book5;
CREATE TABLE book5 (
book_id INT ,
book_name VARCHAR(100),
`authors` VARCHAR(100),
info VARCHAR(100) ,
`comment` VARCHAR(100),
year_publication YEAR
);
ALTER TABLE book5 ADD INDEX idx_cmt(`comment`);
ALTER TABLE book5 ADD UNIQUE INDEX uk_idx_bname(book_name);
ALTER TABLE book5 ADD INDEX mul_bid_bname_info(book_id, book_name, info);
SHOW INDEX FROM book5;
2.3 方式三:CREATE INDEX ... ON ...
DROP TABLE IF EXISTS book6;
CREATE TABLE book6 (
book_id INT ,
book_name VARCHAR(100),
`authors` VARCHAR(100),
info VARCHAR(100) ,
`comment` VARCHAR(100),
year_publication YEAR
);
CREATE INDEX idx_cmt ON book6(`comment`);
CREATE UNIQUE INDEX uk_idx_bname ON book6(book_name);
CREATE INDEX mul_bid_bname_info ON book6(book_id, book_name, info);
SHOW INDEX FROM book6;
3.删除索引的两种方式
3.1 使用ALTER TABLE删除索引
3.2 使用DROP INDEX语句删除索引
提示 删除表中的列时,如果要删除的列为索引的组成部分,则该列也会从索引中删除。如果组成索引的所有列都被删除,则整个索引将被删除。
ALTER TABLE book6 DROP INDEX idx_cmt;
DROP INDEX uk_idx_bname ON book6;
ALTER TABLE book6 DROP COLUMN book_name;
ALTER TABLE book6 DROP COLUMN book_id;
ALTER TABLE book6 DROP COLUMN info;
SHOW INDEX FROM book6;