MySQL索引的測試 (千萬級數據) 以及特色總結|週末學習

本文已參與 週末學習計劃,點擊查看詳情html

這是我參與更文挑戰的第6天,活動詳情查看: 更文挑戰mysql

經過存儲過程插入百萬,千萬數據,來對比使用索引和沒使用索引的區別(普通索引web

建立表

能夠看到這裏建立的索引類型都是 BTREEsql

-- ----------------------------
-- 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;
複製代碼

image-20210606182510055

百萬級數據

在這裏咱們使用存儲過程直接往表裏插入一百萬條數據數據庫

-- ------------ 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%';
複製代碼

mysql8插入百萬數據

索引

先看看錶裏如今有多少條數據緩存

20200822215700

不使用索引

-- 查詢時不使用緩存
SELECT SQL_NO_CACHE * FROM mall WHERE type ='book';
複製代碼

20200822220030

使用索引

-- 添加索引
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

20200822222619

千萬級數據

想要更快地插入能夠修改引擎爲MyISAM,使用jdbc等去批量插入,好比一次插入 5000 甚至更多就能夠了。 在使用 innodb 時,能夠將 autocommit 關閉,插入完數據再去創建索引(後知後覺🙃)。 下圖是改用 MYISAM 後插入 100萬 數據使用的時間。函數

20200823104800

-- 調用上面的存儲過程再插入900w條數據。 這裏用了兩個多小時 。。 
CALL add_mall(900000); 
複製代碼

經過SELECT count(*) FROM mall;看到如今表裏有1200萬條數據post

20200823121400

先簡單介紹下 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引擎下的查詢耗時狀況:

MYISAM

隱藏索引:

20200823123219

顯示索引:

20200823123352

🛫

起飛!✔

Innodb下:

隱藏索引:

20200823135504

顯示索引:

20200823135059

================ 簡單測試結束 😄===================

能夠看到使用索引和不使用索引的速度區別是很是大的!

索引的類型

  • 主鍵索引
  • 普通索引
  • 惟一索引
  • 組合索引
  • 全文索引
  • 空間索引

能夠發現索引的類型是不少的,並且和這個存儲引擎有關

下面介紹幾個常見的存儲引擎的索引特色😄

InnoDB 存儲引擎的索引特色

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

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
SPATIAL N/A No No N/A N/A

Memory 存儲引擎的索引特色

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

歡迎關注,交個朋友呀!! ( •̀ ω •́ )y

嘿嘿,我是4ye 我們下期…… 很快再見!😄

若是你以爲本篇文章對你有所幫助的話,那拜託再點點贊支持一下呀😝

讓咱們開始這一場意外的相遇吧!~

歡迎留言!謝謝支持!ヾ(≧▽≦*)o 沖沖衝!!

相關文章
相關標籤/搜索