数据库——索引
索引的本质
MySQL官方对索引的定义为:索引(Index)是帮助MySQL高效获取数据的数据结构。提取句子主干,就可以得到索引的本质:索引是数据结构。
索引在小数据时用处不大,但在大数据时用处十分明显
索引的分类
- 主键索引(PRIMARY KEY)
- 唯一的标识,主键不可重复,只能有一个列作为主键
- 唯一索引(UNIQUE KEY)
- 避免重复的列出现,唯一索引可以重复,多个列都可以标识为唯一索引
- 常规索引(KEY/INDEX)
- 默认的,不写就有。也可以用index或者key关键字来设置
- 全文索引(FullText)
- 在特定的数据引擎下才有,如MYISAM
- 快速定位数据
索引的使用
创建索引的方式
-- 增加一个索引 格式1: 索引类型 索引名 要加索引的列名
ALTER TABLE `student` ADD FULLTEXT INDEX `studentname`(`studentname`)
-- 增加一个索引 格式二
-- CREATE INDEX(常规索引)/FULLTEXT(全文索引) 索引名 on 表(字段) id_表名字_字段名为索引名
CREATE INDEX id_app_user_name ON`app_user`(`name`) -- 创建索引可以大大增加查询速度
-- 方式三 在建表的时候加索引
CREATE TABLE test1 (
id INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
content TEXT NOT NULL,
PRIMARY KEY(id), -- 建了主键索引
FULLTEXT KEY content_index(content)-- 创建了全文索引
) ENGINE=MYISAM DEFAULT CHARSET=utf8;
删除索引的方式
-- 方式一
DROP INDEX 索引名 ON 表名
-- 方式二
ALTER TABLE 表名 DROP INDEX 索引名
-- 分析SQL执行的状况
EXPLAIN SELECT * FROM student
索引原则
- 索引不是越多越好
- 不要对经常变动的数据加索引
- 小数据量的表不需要加索引
- 索引一般用在经常查询到字段上
索引测试
-- =========================索引==========================
-- 索引的使用
-- 1. 在创建表的时候给字段增加索引
-- 2. 创建完毕后,增加索引
-- 3. 通过ALTER TABLE创建或删除全文索引
-- 4. 直接使用DROP INDEX删除全文索引
-- 显示所有的索引信息
SHOW INDEX FROM student
-- 增加一个索引 格式1: 索引类型 索引名 要加索引的列名
ALTER TABLE `student` ADD FULLTEXT INDEX `studentname`(`studentname`)
-- 分析SQL执行的状况
EXPLAIN SELECT * FROM student -- 非全文索引
EXPLAIN SELECT * FROM student WHERE MATCH(`studentname`) AGAINST('张三')-- 全文索引
/*使用 match 和 against 关键字
注意: match() 函数中指定的列必须和全文索引中指定的列完全相同,否则就会报错,
无法使用全文索引,这是因为全文索引不会记录关键字来自哪一列。
如果想要对某一列使用全文索引,请单独为该列创建全文索引。
*/
SELECT VERSION()
-- 全文索引测试
CREATE TABLE test1 (
id INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
content TEXT NOT NULL,
PRIMARY KEY(id),
FULLTEXT KEY content_index(content)
) ENGINE=MYISAM DEFAULT CHARSET=utf8;
INSERT INTO test1 (content) VALUES ('a'),('b'),('c');
INSERT INTO test1 (content) VALUES ('aa'),('bb'),('cc');
INSERT INTO test1(content) VALUES ('aaa'),('bbb'),('ccc');
INSERT INTO test1 (content) VALUES ('aaaa'),('bbbb'),('cccc');
SELECT * FROM test1 WHERE MATCH(content) AGAINST('a');
SELECT * FROM test1 WHERE MATCH(content) AGAINST('aa');
SELECT * FROM test1 WHERE MATCH(content) AGAINST('aaa');
SELECT * FROM test1 WHERE MATCH(content) AGAINST('aaaa');
SHOW VARIABLES LIKE '%ft%';
-- =====================索引测试========================
CREATE TABLE `app_user` (
`id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
`name` VARCHAR(50) DEFAULT '',
`email` VARCHAR(50) NOT NULL,
`phone` VARCHAR(20) DEFAULT '',
`gender` TINYINT(4) UNSIGNED DEFAULT '0',
`password` VARCHAR(100) NOT NULL DEFAULT '',
`age` TINYINT(4) DEFAULT NULL,
`create_time` DATETIME DEFAULT CURRENT_TIMESTAMP,
`update_time` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=INNODB DEFAULT CHARSET=utf8
-- 百万数据插入
DROP FUNCTION IF EXISTS mock_data;
-- 写函数之前必须要写标志:$$
DELIMITER $$
CREATE FUNCTION mock_data()-- 创建一个函数
RETURNS INT -- 返回一个值
-- 注意returns,否则报错。
BEGIN -- 函数体
DECLARE num INT DEFAULT 1000000;-- num 作为截止数字,定义为百万,
DECLARE i INT DEFAULT 0; -- 定义起始变量
WHILE i < num DO
-- 插入语句
INSERT INTO app_user(`name`, `email`, `phone`, `gender`, `password`, `age`)
VALUES(CONCAT('用户', i), CONCAT('100',i,'[email protected]'), CONCAT('18', FLOOR(RAND()*(999999999-100000000)+100000000)),FLOOR(RAND()*2),UUID(), FLOOR(RAND()*100));
SET i = i + 1;
END WHILE; -- 循环结束
RETURN i;
END;
SELECT mock_data();-- 开始执行
SELECT * FROM `app_user` WHERE `name`='用户1988'
-- 分析SQL执行的状况
EXPLAIN SELECT * FROM `app_user` WHERE `name`='用户1988'-- 显示共查询了991770行数据才查询到'用户1988'的信息
-- 增加一个索引 格式二
-- CREATE INDEX(常规索引)/FULLTEXT(全文索引) 索引名 on 表(字段) id_表名字_字段名为索引名
CREATE INDEX id_app_user_name ON`app_user`(`name`) -- 创建索引可以大大增加查询速度
-- 分析SQL执行的状况
EXPLAIN SELECT * FROM `app_user` WHERE `name`='用户1988'-- 增加索引后,显示只查询了1行数据就查询到'用户1988'的信息