本文已參與 週末學習計劃,點擊查看詳情html
這是我參與更文挑戰的第6天,活動詳情查看: 更文挑戰mysql
經過存儲過程插入百萬,千萬數據,來對比使用索引和沒使用索引的區別(普通索引)web
能夠看到這裏建立的索引類型都是 BTREE
sql
-- ----------------------------
-- Table structure for mall
-- ----------------------------
DROP TABLE IF EXISTS `mall`;
CREATE TABLE `mall` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`categoryId` int(11) NOT NULL,
`name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
`price` decimal(10, 2) NOT NULL,
`type` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`desc` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`img` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
複製代碼
在這裏咱們使用存儲過程直接往表裏插入一百萬條數據數據庫
-- ------------ MYSQL8.0.17 插入百萬數據
-- 獲取數據庫版本
SELECT VERSION();
-- ROUND( ) 四捨五入 第二個參數表示保留兩位小數 ; RAND() 返回 0-1的小數
SELECT ROUND(RAND()*1000,2) as 'test_name';
-- ---------------------------------建立生成隨機字符串函數【START】------------------------------------------------------------------
-- 修改分隔符 避免被MySQL 解析
DELIMITER $$
-- 若是存在就刪除
DROP FUNCTION IF EXISTS rand_str;
-- 建立函數名 rand_str 參數爲返回的長度
create FUNCTION rand_str(strlen SMALLINT )
-- 返回值
RETURNS VARCHAR(255)
BEGIN
-- 聲明的字符串
DECLARE randStr VARCHAR(255) DEFAULT 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890';
-- 聲明 i 循環變量
DECLARE i SMALLINT DEFAULT 0;
-- 聲明返回變量
DECLARE resultStr VARCHAR(255) DEFAULT '';
WHILE i<strlen DO
SET resultStr=CONCAT(SUBSTR(randStr,FLOOR(RAND()*LENGTH(randStr))+1,1),resultStr);
SET i=i+1;
END WHILE;
RETURN resultStr;
END $$
DELIMITER ;
-- ------------------------------------建立生成隨機字符串函數【END】---------------------------------------------------------------
-- 建立函數報錯,可參考 # https://www.cnblogs.com/kerrycode/p/7641835.html
show variables like 'log_bin';
show variables like '%log_bin_trust_function_creators%';
set global log_bin_trust_function_creators=1;
-- 調用隨機字符串函數
select rand_str(FLOOR(RAND()*20));
-- 建立存儲過程 插入1 000 000 數據
DROP PROCEDURE IF EXISTS `add_mall`;
DELIMITER $$
CREATE PROCEDURE `add_mall` ( IN n INT )
BEGIN
DECLARE i INT UNSIGNED DEFAULT 0;
WHILE
i < n DO
INSERT INTO mall ( categoryId, `name`, price, type, `desc`, `img` )
VALUES
( 1, 'test', ROUND( RAND()* 1000, 2 ), rand_str ( FLOOR( RAND()* 20 )), 'test', 'test.jpg' ),
( 1, 'test', ROUND( RAND()* 1000, 2 ), rand_str ( FLOOR( RAND()* 20 )), 'test', 'test.jpg' ),
( 1, 'test', ROUND( RAND()* 1000, 2 ), rand_str ( FLOOR( RAND()* 20 )), 'test', 'test.jpg' ),
( 1, 'test', ROUND( RAND()* 1000, 2 ), rand_str ( FLOOR( RAND()* 20 )), 'test', 'test.jpg' ),
( 1, 'test', ROUND( RAND()* 1000, 2 ), rand_str ( FLOOR( RAND()* 20 )), 'test', 'test.jpg' ),
( 1, 'test', ROUND( RAND()* 1000, 2 ), rand_str ( FLOOR( RAND()* 20 )), 'test', 'test.jpg' ),
( 1, 'test', ROUND( RAND()* 1000, 2 ), rand_str ( FLOOR( RAND()* 20 )), 'test', 'test.jpg' ),
( 1, 'test', ROUND( RAND()* 1000, 2 ), rand_str ( FLOOR( RAND()* 20 )), 'test', 'test.jpg' ),
( 1, 'test', ROUND( RAND()* 1000, 2 ), rand_str ( FLOOR( RAND()* 20 )), 'test', 'test.jpg' ),
( 1, 'test', ROUND( RAND()* 1000, 2 ), rand_str ( FLOOR( RAND()* 20 )), 'test', 'test.jpg' );
SET i = i + 1;
END WHILE;
END $$
DELIMITER;
-- 調用存儲過程 100w 829.876s
CALL add_mall(100000);
-- 若是插入數據報錯,可能須要調整該值大小
show VARIABLES LIKE '%max_allowd_packet%';
複製代碼
先看看錶裏如今有多少條數據緩存
-- 查詢時不使用緩存
SELECT SQL_NO_CACHE * FROM mall WHERE type ='book';
複製代碼
-- 添加索引
ALTER TABLE mall ADD INDEX idx_book(type);
-- 刪除索引
DROP INDEX idx_book ON mall;
SELECT SQL_NO_CACHE * FROM mall WHERE type ='book';
複製代碼
能夠看到在使用索引以後 這個查詢簡直是飛快,直接變成 1ms ,對比以前 656ms 的速度 👀markdown
想要更快地插入能夠修改引擎爲MyISAM,使用jdbc等去批量插入,好比一次插入 5000 甚至更多就能夠了。 在使用 innodb
時,能夠將 autocommit
關閉,插入完數據再去創建索引(後知後覺🙃)。 下圖是改用 MYISAM
後插入 100萬 數據使用的時間。函數
-- 調用上面的存儲過程再插入900w條數據。 這裏用了兩個多小時 。。
CALL add_mall(900000);
複製代碼
經過SELECT count(*) FROM mall;
看到如今表裏有1200萬條數據post
先簡單介紹下 MySQL8
新特性的隱藏索引,通常建立索引比較耗時的(在數據量大的狀況下),如今有了這個隱藏索引,咱們測試起來就更方便了,實際應用中還能夠避免誤刪索引。學習
-- mysql8新特性之隱藏索引
alter TABLE mall ALTER INDEX idx_book invisible;
-- 顯示索引
alter TABLE mall ALTER INDEX idx_book visible;
-- 簡單測試SQL
SELECT SQL_NO_CACHE name,type,price,`desc`,img FROM mall WHERE type = 'book'
複製代碼
接下來咱們試試這個MYISAM
引擎下的查詢耗時狀況:
🛫
起飛!✔
================ 簡單測試結束 😄===================
能夠看到使用索引和不使用索引的速度區別是很是大的!
能夠發現索引的類型是不少的,並且和這個存儲引擎有關
下面介紹幾個常見的存儲引擎的索引特色😄
Index Class | Index Type | Stores NULL VALUES | Permits Multiple NULL Values | IS NULL Scan Type | IS NOT NULL Scan Type |
---|---|---|---|---|---|
Primary key | BTREE |
No | No | N/A | N/A |
Unique | BTREE |
Yes | Yes | Index | Index |
Key | BTREE |
Yes | Yes | Index | Index |
FULLTEXT |
N/A | Yes | Yes | Table | Table |
Index Class | Index Type | Stores NULL VALUES | Permits Multiple NULL Values | IS NULL Scan Type | IS NOT NULL Scan Type |
---|---|---|---|---|---|
Primary key | BTREE |
No | No | N/A | N/A |
Unique | BTREE |
Yes | Yes | Index | Index |
Key | BTREE |
Yes | Yes | Index | Index |
FULLTEXT |
N/A | Yes | Yes | Table | Table |
SPATIAL |
N/A | No | No | N/A | N/A |
Index Class | Index Type | Stores NULL VALUES | Permits Multiple NULL Values | IS NULL Scan Type | IS NOT NULL Scan Type |
---|---|---|---|---|---|
Primary key | BTREE |
No | No | N/A | N/A |
Unique | BTREE |
Yes | Yes | Index | Index |
Key | BTREE |
Yes | Yes | Index | Index |
Primary key | HASH |
No | No | N/A | N/A |
Unique | HASH |
Yes | Yes | Index | Index |
Key | HASH |
Yes | Yes | Index | Index |
嘿嘿,我是4ye 我們下期…… 很快再見!😄
若是你以爲本篇文章對你有所幫助的話,那拜託再點點贊支持一下呀😝
讓咱們開始這一場意外的相遇吧!~
歡迎留言!謝謝支持!ヾ(≧▽≦*)o 沖沖衝!!