在效能測試、分頁功能驗證或大量資料模擬時,逐筆 INSERT 效率極低。MySQL 提供一種巧妙的「表自我複製」技巧,能以指數級速度讓資料量快速膨脹,幾條指令即可從幾筆測試資料產生百萬級測試集。
INSERT INTO target_table (col1, col2, ...)
SELECT col1, col2, ... FROM target_table;
AUTO_INCREMENT,必須明確列出欄位名稱,排除主鍵欄位,否則會因主鍵衝突報錯。
-- 假設 id 為自增主鍵
INSERT INTO t1 (col1, col2) SELECT col1, col2 FROM t1;
CREATE TABLE `user_log` (
`id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
`user_id` INT NOT NULL,
`action` VARCHAR(32) NOT NULL,
`created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
INSERT INTO `user_log` (`user_id`, `action`) VALUES
(1, 'login'), (2, 'view'), (3, 'purchase'), (4, 'logout'), (5, 'login');
| 執行次數 | 預估資料筆數 | 執行時間參考(SSD、InnoDB) |
|---|---|---|
| 0 (種子) | 5 | — |
| 1 | 10 | < 0.01 秒 |
| 5 | 160 | < 0.01 秒 |
| 10 | 5,120 | 0.02 秒 |
| 15 | 163,840 | 0.3 秒 |
| 20 | 5,242,880 | 2.5 秒 |
| 24 | 83,886,080 | 約 15 秒 |
幾十秒內即可產生千萬級測試資料,滿足大多數效能測試需求。
INSERT INTO `user_log` (`user_id`, `action`, `created_at`)
SELECT
`user_id` + 1000,
CONCAT(`action`, '_copy'),
DATE_ADD(`created_at`, INTERVAL 1 DAY)
FROM `user_log`;
避免資料完全重複,更接近真實場景。
INSERT INTO `t1` (`a`, `b`)
SELECT `a`, `b` FROM `t1` WHERE `id` < 10000;
控制每輪增長量,避免單次交易過大導致鎖爭用或複製日誌暴增。
innodb_log_file_size。SET sql_log_bin=0 跳過二進制日誌(僅限測試庫)。DROP INDEX 複製完再 CREATE INDEX,速度提升數倍。| 方法 | 優點 | 缺點 | 適用場景 |
|---|---|---|---|
自我複製 INSERT...SELECT | SQL 原生、無外部工具、指數增長極快 | 資料單一、需注意主鍵、日誌膨脹 | 快速產生大量結構固定測試資料 |
LOAD DATA INFILE | 極速、可自定義資料內容 | 需準備外部檔案、權限設定較繁瑣 | 需特定分佈資料、導入外部資料集 |
| 存儲過程/腳本循環 INSERT | 邏輯靈活、可生成隨機資料 | 速度慢、開發維護成本高 | 複雜業務邏輯測試資料生成 |
| 第三方工具 | 功能豐富、視覺化 | 需安裝學習、可能收費 | 長期、標準化測試資料管理 |
MySQL 的 INSERT INTO ... SELECT ... FROM 同一張表 是快速製造大量測試資料的「秘密武器」。掌握主鍵排除、分批執行、索引暫停等技巧,能在幾分鐘內從零建立千萬級測試資料集,大幅提升測試準備效率。記得:僅限測試/開發環境使用,生產環境嚴禁直接操作!