MySQL如何實(shí)現(xiàn)快速插入大量測(cè)試數(shù)據(jù)
1.1. 簡(jiǎn)述
開(kāi)發(fā)過(guò)程中經(jīng)常需要測(cè)試 SQL 在大量數(shù)據(jù)集時(shí)候的執(zhí)行效率, 這就需要我們?cè)诒碇胁迦氪罅康臏y(cè)試數(shù)據(jù), 下面介紹如何使用存儲(chǔ)過(guò)程插入大量的測(cè)試數(shù)據(jù)
1.2. 定義常用方法
我們要確保生成的測(cè)試數(shù)據(jù)要有足夠的隨機(jī)性, 測(cè)試結(jié)果才會(huì)更準(zhǔn)確, 如果某個(gè)字段的測(cè)試數(shù)據(jù)都是一樣的, 索引的效率會(huì)大大折扣, 測(cè)試結(jié)果往往與真實(shí)數(shù)據(jù)的執(zhí)行結(jié)果大相徑庭
我們可以使用 MySQL 的自定義函數(shù)來(lái)實(shí)現(xiàn)隨機(jī)值的生成, 下面羅列出幾種常見(jiàn)的字段的函數(shù)定義
1.2.1. 生成隨機(jī)時(shí)間
函數(shù)聲明:
CREATE DEFINER=`root`@`%` FUNCTION `genDate`(
start_time VARCHAR(10),
end_time VARCHAR(10)
) RETURNS VARCHAR(255) CHARSET utf8mb4
BEGIN
DECLARE random_date DATETIME DEFAULT NULL;
SET random_date = CONCAT(
(DATE(FROM_UNIXTIME(UNIX_TIMESTAMP(start_time) + FLOOR(RAND() * (UNIX_TIMESTAMP(end_time) - UNIX_TIMESTAMP(start_time) + 1))))),
' ',
FLOOR(RAND() * 24), ':', FLOOR(RAND() * 60), ':', FLOOR(RAND() * 60)
);
RETURN date_format(random_date,'%Y-%m-%d %H:%i:%s');
END
使用示例:
生成 2020-01-01 ~ 2023-01-01 時(shí)間段內(nèi)的隨機(jī)時(shí)間
> select genDate('2020-01-01','2023-01-01');
2020-06-22 4:25:35
1.2.2. 生成中文名
函數(shù)聲明:
CREATE DEFINER=`root`@`%` FUNCTION `genUsername`() RETURNS varchar(255) CHARSET utf8mb4
BEGIN
DECLARE first_name_dict VARCHAR(2056) DEFAULT '趙錢(qián)孫李周鄭王馮陳楮衛(wèi)蔣沈韓楊朱秦尤許何呂施張孔曹?chē)?yán)華金魏陶姜戚謝喻柏水竇章云蘇潘葛奚范彭郎魯韋昌馬苗鳳花方俞任袁柳酆鮑史唐費(fèi)廉岑薛雷賀倪湯滕殷羅畢郝鄔安常樂(lè)于時(shí)傅皮齊康伍余元卜顧孟平黃和穆蕭尹姚邵湛汪祁毛禹狄米貝明臧計(jì)伏成戴談宋茅龐熊紀(jì)舒屈項(xiàng)祝董梁杜阮藍(lán)閩席季麻強(qiáng)賈路婁危江童顏郭梅盛林刁鍾徐丘駱高夏蔡田樊胡凌霍虞萬(wàn)支柯昝管盧莫經(jīng)裘繆干解應(yīng)宗丁宣賁鄧郁單杭洪包諸左石崔吉鈕龔程嵇邢滑裴陸榮翁';
DECLARE last_name_dict VARCHAR(2056) DEFAULT '嘉懿煜城懿軒燁偉苑博偉澤熠彤鴻煊博濤燁霖?zé)钊A煜祺智宸正豪昊然明杰誠(chéng)立軒立輝峻熙弘文熠彤鴻煊燁霖哲瀚鑫鵬致遠(yuǎn)俊馳雨澤燁磊晟睿天佑文昊修潔黎昕遠(yuǎn)航旭堯鴻濤偉祺軒越澤浩宇瑾瑜皓軒擎蒼擎宇志澤睿淵楷瑞軒弘文哲瀚雨澤鑫磊夢(mèng)琪憶之桃慕青問(wèn)蘭爾嵐元香初夏沛菡傲珊曼文樂(lè)菱癡珊恨玉惜文香寒新柔語(yǔ)蓉海安夜蓉涵柏水桃醉藍(lán)春兒語(yǔ)琴?gòu)耐燎缯Z(yǔ)蘭又菱碧彤元霜憐夢(mèng)紫寒妙彤曼易南蓮紫翠雨寒易煙如萱若南尋真曉亦向珊慕靈以蕊尋雁映易雪柳孤嵐笑霜海云凝天沛珊寒云冰旋宛兒綠真盼兒曉霜碧凡夏菡曼香若煙半夢(mèng)雅綠冰藍(lán)靈槐平安書(shū)翠翠風(fēng)香巧代云夢(mèng)曼幼翠友巧聽(tīng)寒夢(mèng)柏醉易訪(fǎng)旋亦玉凌萱訪(fǎng)卉懷亦笑藍(lán)春翠靖柏夜蕾冰夏夢(mèng)松書(shū)雪樂(lè)楓念薇靖雁尋春恨山從寒憶香覓波靜曼凡旋以亦念露芷蕾千蘭新波代真新蕾雁玉冷卉紫山千琴恨天傲芙盼山懷蝶冰蘭山柏翠萱樂(lè)丹翠柔谷山之瑤冰露爾珍谷雪樂(lè)萱涵菡海蓮傲蕾青槐冬兒易夢(mèng)惜雪宛海之柔夏青亦瑤妙菡春竹修杰偉誠(chéng)建輝晉鵬天磊紹輝澤洋明軒健柏煊昊強(qiáng)偉宸博超君浩子騫明輝鵬濤炎彬鶴軒越彬風(fēng)華靖琪明誠(chéng)高格光華國(guó)源宇晗昱涵潤(rùn)翰飛翰海昊乾浩博和安弘博鴻朗華奧華燦嘉慕堅(jiān)秉建明金鑫錦程瑾瑜鵬經(jīng)賦景同靖琪君昊俊明季同開(kāi)濟(jì)凱安康成樂(lè)語(yǔ)力勤良哲理群茂彥敏博明達(dá)朋義彭澤鵬舉濮存溥心璞瑜浦澤奇邃祥榮軒';
DECLARE first_name VARCHAR(3) DEFAULT substring(first_name_dict, floor(length(first_name_dict) / 3 * rand()), 1);
DECLARE last_name VARCHAR(9);
DECLARE full_name_length INT DEFAULT FLOOR(2+(RAND()*3))*3;
DECLARE full_name VARCHAR(12) DEFAULT first_name;
WHILE LENGTH(full_name) < full_name_length DO
SET full_name = CONCAT(full_name, substring(last_name_dict, floor(length(last_name_dict) / 3 * rand()), 1));
END WHILE;
return full_name;
END
使用示例:
> select genUsername(); 凌之澤
1.2.3. 字符串分割選取
函數(shù)聲明:
CREATE FUNCTION `splitStr` (
str VARCHAR (1000),
delimiter VARCHAR (5),
str_order INT
) RETURNS VARCHAR (255) CHARSET utf8mb4 DETERMINISTIC
BEGIN
DECLARE result VARCHAR (255) DEFAULT '';
SET result = REVERSE(
substring_index(
REVERSE(
substring_index(
str,
delimiter,
str_order
)
),
delimiter,
1
)
);
RETURN result;
END
使用示例: 該函數(shù)用于將字符串按照指定的分割符進(jìn)行分割, 并返回分割后的第 n(n 由參數(shù)指定) 個(gè)字符串, 如取字符串"I love MySQL"按空格分割后的第 2 個(gè)字符串
> select splitStr('I love MySQL',' ','2);
love
1.2.4. 生成隨機(jī)手機(jī)號(hào)
函數(shù)聲明:
CREATE DEFINER=`root`@`%` FUNCTION `genMobile`() RETURNS char(11) CHARSET utf8mb4 NOT DETERMINISTIC
BEGIN
DECLARE head VARCHAR(100) DEFAULT '132,133,139,183,186,187,130,131,189,151,156,157,176,134,135,137,138,136,000';
DECLARE content CHAR(10) DEFAULT '0123456789';
DECLARE phone CHAR(20) DEFAULT splitStr(head, ',', FLOOR(1 + RAND() * 19));
DECLARE i int DEFAULT 1;
WHILE i<9 DO
SET i=i+1;
SET phone = CONCAT(phone, substring(content, floor(1 + RAND() * 10), 1));
END WHILE;
RETURN phone;
END
使用示例:
> select genMobile(); 18975304923
1.3. 插入大量測(cè)試數(shù)據(jù)
如下面這張表, 現(xiàn)在要插入 10w 的測(cè)試數(shù)據(jù), 我們可以定義一個(gè) MySQL 存儲(chǔ)過(guò)程, 通過(guò)存儲(chǔ)過(guò)程的方式插入數(shù)據(jù)到表中
表結(jié)構(gòu)
CREATE TABLE `t_user` ( `user_id` int(11) NOT NULL AUTO_INCREMENT, `username` varchar(50) DEFAULT NULL, `sex` tinyint(1) DEFAULT NULL, `mobile` varchar(45) DEFAULT NULL, `create_time` datetime DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`user_id`), KEY `idx_create_time` (`create_time`) USING BTREE ) ENGINE=InnoDB AUTO_INCREMENT=100001 DEFAULT CHARSET=utf8mb4
存儲(chǔ)過(guò)程定義
CREATE DEFINER=`root`@`%` PROCEDURE `t_user_batch_insert`(IN size INT)
BEGIN
declare i int default 0;
while i < size do
insert into t_user(username,sex,mobile) values(genUsername(),floor(rand() * 2),genMobile());
set i = i + 1;
end while;
END
調(diào)用存儲(chǔ)過(guò)程
> call t_user_batch_insert(100000);
在我這邊, 插入 10w 條數(shù)據(jù), 只要 52s
1.3.1. 延伸
除了使用存儲(chǔ)過(guò)程的方法插入數(shù)據(jù)外, 還可以通過(guò)代碼的方式插入數(shù)據(jù), 但是該方法的執(zhí)行效率不高。
另外, 如果你有 navicat 的話(huà), 也可以試試 navicat 的數(shù)據(jù)生成方案, 由于我沒(méi)有 navicat, 就不介紹了, 感興趣的可以看 navicat 的文檔
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
MySQL Docker容器中XA事務(wù)鎖故障的終極排查指南
本文記錄了一次生產(chǎn)環(huán)境中MySQL XA事務(wù)鎖故障的完整排查過(guò)程,從問(wèn)題發(fā)現(xiàn)到最終解決,涵蓋了分布式事務(wù)原理、Docker數(shù)據(jù)持久化、MySQL恢復(fù)機(jī)制等深度技術(shù)細(xì)節(jié)2025-11-11
MySQL中必須了解的13個(gè)關(guān)鍵字總結(jié)
這篇文章主要為大家詳細(xì)介紹了MySQL中必須了解學(xué)會(huì)的13個(gè)關(guān)鍵字,文中的示例代碼簡(jiǎn)潔易懂,對(duì)我們掌握MySQL有一定的幫助,需要的可以了解下2023-09-09
mysql 8.0.18 安裝配置方法圖文教程(linux)
這篇文章主要介紹了linux下mysql 8.0.18 安裝配置方法圖文教程,文中安裝步驟介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-11-11
升級(jí)到mysql-connector-java8.0.27的注意事項(xiàng)
這篇文章主要介紹了升級(jí)到mysql-connector-java8.0.27的注意事項(xiàng),凡是升級(jí)總會(huì)碰到點(diǎn)問(wèn)題,換了連接器后部署果然報(bào)錯(cuò)了,下面小編給大家分享解決方法,需要的朋友可以參考下2021-12-12
MySQL中TEXT類(lèi)型存儲(chǔ)極限與實(shí)踐案例
本文解析MySQL TEXT類(lèi)型存儲(chǔ)極限及工程實(shí)踐,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧2022-10-10
MySQL數(shù)據(jù)備份之mysqldump的使用方法
mysqldump常用于MySQL數(shù)據(jù)庫(kù)邏輯備份,這篇文章主要給大家介紹了關(guān)于MySQL數(shù)據(jù)備份之mysqldump使用的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2021-11-11

