日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

MySQL 快速创建千万级测试数据

發布時間:2025/3/11 数据库 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 MySQL 快速创建千万级测试数据 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

作者:IKNOW本尊

鏈接:http://t.cn/E96Shud

背景

在進行查詢操作的性能測試或者 sql 優化時,我們經常需要在線下環境構建大量的基礎數據供我們測試,模擬線上的真實環境。

總不能讓我去線上去測試吧,會被DBA砍死的

創建測試數據的方式

1. 編寫代碼,通過代碼批量插庫(本人使用過,步驟太繁瑣,性能不高,不推薦)2. 編寫存儲過程和函數執行(本文實現方式1)3. 臨時數據表方式執行 (本文實現方式2,強烈推薦該方式,非常簡單,數據插入快速,100W,只需幾秒)4. 一行一行手動插入,(WTF,去死吧)

創建基礎表結構

不管用何種方式,我要插在那張表總要創建的吧

CREATE TABLE `t_user` (`id` int(11) NOT NULL AUTO_INCREMENT,`c_user_id` varchar(36) NOT NULL DEFAULT '',`c_name` varchar(22) NOT NULL DEFAULT '',`c_province_id` int(11) NOT NULL,`c_city_id` int(11) NOT NULL,`create_time` datetime NOT NULL,PRIMARY KEY (`id`),KEY `idx_user_id` (`c_user_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

方式1:采用存儲過程和內存表

  • 創建內存表

利用 MySQL 內存表插入速度快的特點,我們先利用函數和存儲過程在內存表中生成數據,然后再從內存表插入普通表中 CREATE TABLE `t_user_memory` (`id` int(11) NOT NULL AUTO_INCREMENT,`c_user_id` varchar(36) NOT NULL DEFAULT '',`c_name` varchar(22) NOT NULL DEFAULT '',`c_province_id` int(11) NOT NULL,`c_city_id` int(11) NOT NULL,`create_time` datetime NOT NULL,PRIMARY KEY (`id`),KEY `idx_user_id` (`c_user_id`) ) ENGINE=MEMORY DEFAULT CHARSET=utf8mb4;
  • 創建函數和存儲過程

# 創建隨機字符串和隨機時間的函數 mysql> delimiter $$ mysql> CREATE DEFINER=`root`@`%` FUNCTION `randStr`(n INT) RETURNS varchar(255) CHARSET utf8mb4-> DETERMINISTIC-> BEGIN-> DECLARE chars_str varchar(100) DEFAULT 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';-> DECLARE return_str varchar(255) DEFAULT '' ;-> DECLARE i INT DEFAULT 0;-> WHILE i < n DO-> SET return_str = concat(return_str, substring(chars_str, FLOOR(1 + RAND() * 62), 1));-> SET i = i + 1;-> END WHILE;-> RETURN return_str;-> END$$ Query OK, 0 rows affected (0.00 sec) mysql> CREATE DEFINER=`root`@`%` FUNCTION `randDataTime`(sd DATETIME,ed DATETIME) RETURNS datetime-> DETERMINISTIC-> BEGIN-> DECLARE sub INT DEFAULT 0;-> DECLARE ret DATETIME;-> SET sub = ABS(UNIX_TIMESTAMP(ed)-UNIX_TIMESTAMP(sd));-> SET ret = DATE_ADD(sd,INTERVAL FLOOR(1+RAND()*(sub-1)) SECOND);-> RETURN ret;-> END $$ mysql> delimiter ; # 創建插入數據存儲過程 mysql> CREATE DEFINER=`root`@`%` PROCEDURE `add_t_user_memory`(IN n int)-> BEGIN-> DECLARE i INT DEFAULT 1;-> WHILE (i <= n) DO-> INSERT INTO t_user_memory (c_user_id, c_name, c_province_id,c_city_id, create_time) VALUES (uuid(), randStr(20), FLOOR(RAND() * 1000), FLOOR(RAND() * 100), NOW());-> SET i = i + 1;-> END WHILE;-> END-> $$ Query OK, 0 rows affected (0.01 sec)
  • 調用存儲過程

mysql> CALL add_t_user_memory(1000000); ERROR 1114 (HY000): The table 't_user_memory' is full 出現內存已滿時,修改 max_heap_table_size 參數的大小,我使用64M內存,插入了22W數據,看情況改,不過這個值不要太大,默認32M或者64M就好,生產環境不要亂嘗試
  • 從內存表插入普通表

mysql> INSERT INTO t_user SELECT * FROM t_user_memory; Query OK, 218953 rows affected (1.70 sec) Records: 218953 Duplicates: 0 Warnings: 0

方式2:采用臨時表

  • 創建臨時數據表tmp_table

CREATE TABLE tmp_table (id INT,PRIMARY KEY (id) );
  • 用 python或者bash 生成 100w 記錄的數據文件(python瞬間就會生成完)

python(推薦): python -c "for i in range(1, 1+1000000): print(i)" > base.txt
  • 導入數據到臨時表tmp_table中

mysql> load data infile '/Users/LJTjintao/temp/base.txt' replace into table tmp_table; Query OK, 1000000 rows affected (2.55 sec) Records: 1000000 Deleted: 0 Skipped: 0 Warnings: 0 千萬級數據 20秒插入完成

注意:導入數據時有可能會報錯,原因是mysql默認沒有開securefilepriv( 這個參數用來限制數據導入和導出操作的效果,例如執行LOAD DATA、SELECT … INTO OUTFILE語句和LOAD_FILE()函數。這些操作需要用戶具有FILE權限 )。

解決辦法:在mysql的配置文件中(my.ini 或者 my.conf)中添加 securefilepriv = /Users/LJTjintao/temp/`, 然后重啟mysql 解決

  • 以臨時表為基礎數據,插入數據到t_user中,100W數據插入需要10.37s

mysql> INSERT INTO t_user-> SELECT-> id,-> uuid(),-> CONCAT('userNickName', id),-> FLOOR(Rand() * 1000),-> FLOOR(Rand() * 100),-> NOW()-> FROM-> tmp_table; Query OK, 1000000 rows affected (10.37 sec) Records: 1000000 Duplicates: 0 Warnings: 0
  • 更新創建時間字段讓插入的數據的創建時間更加隨機

UPDATE t_user SET create_time=date_add(create_time, interval FLOOR(1 + (RAND() * 7)) year); Query OK, 1000000 rows affected (5.21 sec) Rows matched: 1000000 Changed: 1000000 Warnings: 0 mysql> UPDATE t_user SET create_time=date_add(create_time, interval FLOOR(1 + (RAND() * 7)) year); Query OK, 1000000 rows affected (4.77 sec) Rows matched: 1000000 Changed: 1000000 Warnings: 0 mysql> select * from t_user limit 30; +----+--------------------------------------+----------------+---------------+-----------+---------------------+ | id | c_user_id | c_name | c_province_id | c_city_id | create_time | +----+--------------------------------------+----------------+---------------+-----------+---------------------+ | 1 | bf5e227a-7b84-11e9-9d6e-751d319e85c2 | userNickName1 | 84 | 64 | 2015-11-13 21:13:19 | | 2 | bf5e26f8-7b84-11e9-9d6e-751d319e85c2 | userNickName2 | 967 | 90 | 2019-11-13 20:19:33 | | 3 | bf5e2810-7b84-11e9-9d6e-751d319e85c2 | userNickName3 | 623 | 40 | 2014-11-13 20:57:46 | | 4 | bf5e2888-7b84-11e9-9d6e-751d319e85c2 | userNickName4 | 140 | 49 | 2016-11-13 20:50:11 | | 5 | bf5e28f6-7b84-11e9-9d6e-751d319e85c2 | userNickName5 | 47 | 75 | 2016-11-13 21:17:38 | | 6 | bf5e295a-7b84-11e9-9d6e-751d319e85c2 | userNickName6 | 642 | 94 | 2015-11-13 20:57:36 | | 7 | bf5e29be-7b84-11e9-9d6e-751d319e85c2 | userNickName7 | 780 | 7 | 2015-11-13 20:55:07 | | 8 | bf5e2a4a-7b84-11e9-9d6e-751d319e85c2 | userNickName8 | 39 | 96 | 2017-11-13 21:42:46 | | 9 | bf5e2b58-7b84-11e9-9d6e-751d319e85c2 | userNickName9 | 731 | 74 | 2015-11-13 22:48:30 | | 10 | bf5e2bb2-7b84-11e9-9d6e-751d319e85c2 | userNickName10 | 534 | 43 | 2016-11-13 22:54:10 | | 11 | bf5e2c16-7b84-11e9-9d6e-751d319e85c2 | userNickName11 | 572 | 55 | 2018-11-13 20:05:19 | | 12 | bf5e2c70-7b84-11e9-9d6e-751d319e85c2 | userNickName12 | 71 | 68 | 2014-11-13 20:44:04 | | 13 | bf5e2cca-7b84-11e9-9d6e-751d319e85c2 | userNickName13 | 204 | 97 | 2019-11-13 20:24:23 | | 14 | bf5e2d2e-7b84-11e9-9d6e-751d319e85c2 | userNickName14 | 249 | 32 | 2019-11-13 22:49:43 | | 15 | bf5e2d88-7b84-11e9-9d6e-751d319e85c2 | userNickName15 | 900 | 51 | 2019-11-13 20:55:26 | | 16 | bf5e2dec-7b84-11e9-9d6e-751d319e85c2 | userNickName16 | 854 | 74 | 2018-11-13 22:07:58 | | 17 | bf5e2e50-7b84-11e9-9d6e-751d319e85c2 | userNickName17 | 136 | 46 | 2013-11-13 21:53:34 | | 18 | bf5e2eb4-7b84-11e9-9d6e-751d319e85c2 | userNickName18 | 897 | 10 | 2018-11-13 20:03:55 | | 19 | bf5e2f0e-7b84-11e9-9d6e-751d319e85c2 | userNickName19 | 829 | 83 | 2013-11-13 20:38:54 | | 20 | bf5e2f68-7b84-11e9-9d6e-751d319e85c2 | userNickName20 | 683 | 91 | 2019-11-13 20:02:42 | | 21 | bf5e2fcc-7b84-11e9-9d6e-751d319e85c2 | userNickName21 | 511 | 81 | 2013-11-13 21:16:48 | | 22 | bf5e3026-7b84-11e9-9d6e-751d319e85c2 | userNickName22 | 562 | 35 | 2019-11-13 20:15:52 | | 23 | bf5e3080-7b84-11e9-9d6e-751d319e85c2 | userNickName23 | 91 | 39 | 2016-11-13 20:28:59 | | 24 | bf5e30da-7b84-11e9-9d6e-751d319e85c2 | userNickName24 | 677 | 21 | 2016-11-13 21:37:15 | | 25 | bf5e3134-7b84-11e9-9d6e-751d319e85c2 | userNickName25 | 50 | 60 | 2018-11-13 20:39:20 | | 26 | bf5e318e-7b84-11e9-9d6e-751d319e85c2 | userNickName26 | 856 | 47 | 2018-11-13 21:24:53 | | 27 | bf5e31e8-7b84-11e9-9d6e-751d319e85c2 | userNickName27 | 816 | 65 | 2014-11-13 22:06:26 | | 28 | bf5e324c-7b84-11e9-9d6e-751d319e85c2 | userNickName28 | 806 | 7 | 2019-11-13 20:17:30 | | 29 | bf5e32a6-7b84-11e9-9d6e-751d319e85c2 | userNickName29 | 973 | 63 | 2014-11-13 21:08:09 | | 30 | bf5e3300-7b84-11e9-9d6e-751d319e85c2 | userNickName30 | 237 | 29 | 2018-11-13 21:48:17 | +----+--------------------------------------+----------------+---------------+-----------+---------------------+ 30 rows in set (0.01 sec)

注意:此文章的數據量在100W,如果想要千萬級,調大數量即可,但是不要大量使用rand() 或者uuid() 會導致性能下降。

往期精彩


喜慶王磊的博客搬遷!無套路送機械鍵盤

面試官問你MySQL的優化,看這篇文章就夠了

經典面試題:如何保證緩存與數據庫的雙寫一致性??

關注下方二維碼,訂閱更多精彩內容。

轉發朋友圈,是對我最大的支持。


總結

以上是生活随笔為你收集整理的MySQL 快速创建千万级测试数据的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。