Mysql官方對索引的定義是:索引(index)是幫助Mysql高效獲取數據的數據結構。進而,我們可以知道索引的本質是數據結構。
一、索引的分類
- 主鍵索引:也就是我們常見的 PRIMARY KEY,只有一個列作為主鍵,唯一標識,不可重復。
- 唯一索引:UNIQUE KEY,避免重復的列出現,唯一索引是可以有多個,同一張表里的多個列都可以設置唯一索引。
- 常規索引:KEY/INDEX,默認的類型,通過關鍵字
INDEX
或者KEY
來設置。 - 全文索引:FullText,在特定的數據庫引擎下才支持,作用是快速定位數據。
二、使用索引
在創建表或者創建之后,都可以給字段增加索引。
比如現在創建一個測試用的表,我先在創建的時候加了前三種類型的索引:
-- 創建表
CREATE TABLE `student`(
`StudentNo` INT(4) NOT NULL COMMENT "學號",
`LoginPwd` VARCHAR(20) DEFAULT NULL,
`StudentName` VARCHAR(20) DEFAULT NULL COMMENT "學生姓名",
`Sex` TINYINT(1) DEFAULT NULL COMMENT "性別:0-1",
`GradeId` INT(11) DEFAULT NULL COMMENT "年紀編號",
`Phone` VARCHAR(50) NOT NULL COMMENT "聯系電話",
`Address` VARCHAR(255) NOT NULL COMMENT "地址",
`BornDate` DATETIME DEFAULT NULL COMMENT "出生日期",
`Email` VARCHAR(50) NOT NULL COMMENT "郵箱",
`IdentityCard` VARCHAR(18) DEFAULT NULL COMMENT "身份證號",
PRIMARY KEY (`StudentNo`), -- 主鍵索引
UNIQUE KEY `IdentityCard` (`IdentityCard`), -- 唯一索引,前面是索引名稱,括號里是字段名
KEY `Email` (`Email`) -- 常規索引
)ENGINE=INNODB DEFAULT CHARSET=utf8;
執行sql,創建表成功。這時候我繼續增加一個全文索引。
-- 增加一個全文索引類型,前面是索引名稱,括號里是字段名
ALTER TABLE `school`.`student` ADD FULLTEXT INDEX `StudentName` (`StudentName`);
可以查看student表的所有索引SHOW INDEX FROM student;
還有第三種,CREATE INDEX 索引名 on 表(字段)
,到后面演示。
三、百萬數據測試索引效果
1. 再來創建個測試表
-- 創建表
CREATE TABLE `app_user`(
`id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
`name` VARCHAR(50) DEFAULT '' COMMENT '昵稱',
`email` VARCHAR(50) DEFAULT NULL COMMENT "郵箱",
`phone` VARCHAR(20) DEFAULT NULL COMMENT "手機號",
`gender` TINYINT(4) DEFAULT NULL COMMENT "性別 0-男, 1-女",
`password` VARCHAR(100) NOT NULL COMMENT "密碼",
`age` TINYINT(4) NOT NULL COMMENT "年齡",
`create_time` DATETIME DEFAULT CURRENT_TIMESTAMP,
`update_time` TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
)ENGINE=INNODB DEFAULT CHARSET=utf8 COMMENT='app用戶表';
執行創建成功,現在插入數據。
2. 插入數據
-- 插入百萬數據
DELIMITER $$
CREATE FUNCTION mock_data()
RETURNS INT
BEGIN
DECLARE num INT DEFAULT 1000000;
DECLARE i INT DEFAULT 0;
WHILE i < num DO
-- 插入語句
INSERT INTO `school`.`app_user`(`name`,`email`,`phone`,`gender`,`password`,`age`)VALUES
(CONCAT('用戶',i), '123456@qq.com', CONCAT('18', FLOOR(RAND()*((999999999-100000000)+100000000))),
FLOOR(RAND()*2), UUID(), FLOOR(RAND()*100));
SET i = i+1;
END WHILE;
RETURN i;
END;
執行可能會出現This function has none of DETERMINISTIC, NO SQL, or READS SQL DATA in its declaration and binary
報錯。
如果出現,可以先執行set global log_bin_trust_function_creators=TRUE
,然后再試下。
執行成功后,再執行:
SELECT mock_data();
大概持續1分鍾左右,別急。
3. 測試查詢
未加索引
查詢一條數據。
SELECT * FROM `app_user` WHERE `name`='用戶9999'
多次執行查詢,發現花費時間,穩定在0.63s
左右,這個從點擊執行到看到結果,已經從肉眼可以感知有點慢了。
我們可以增加關鍵詞EXPLAIN
分析sql執行的情況。
EXPLAIN SELECT * FROM `app_user` WHERE `name`='用戶9999'
可以看到這個語句查了99W+條,這都是時間消耗。
添加索引
用上面說的第三種方式,增加一個常規索引。
CREATE INDEX id_app_user_name ON app_user(`name`);
再重新執行下查詢:
SELECT * FROM `app_user` WHERE `name`='用戶9999'
查詢時間大幅縮短,只需要要0.1s+。
再分析下加了索引后的查詢。
EXPLAIN SELECT * FROM `app_user` WHERE `name`='用戶9999'
只查了一條,精准查詢。
三、索引使用原則
索引雖然好用,但是不可以濫用,這里有幾個原則可以記一下:
- 索引不是越多越好。
- 不要對經常變動的數據加索引。
- 小數據量的表不需要加索引。
- 索引一般加在常用來查詢的字段上。
以上就是對索引的簡單介紹,但是MySQL索引背后的數據結構及算法原理,東西可就多了,有一個大佬講的挺細的,有興趣可以翻下,傳送門