DATE 型別欄位(原 DATETIME)。SELECT * FROM tb WHERE id > 40000 AND id < 50001
INTO OUTFILE '/tmp/data.txt';
LOAD DATA INFILE '/tmp/data.txt' INTO TABLE new_tb;
問題:OFFSET 大時全表掃描,單批 1 萬行耗時不可接受。
-- 確認分區裁剪生效
EXPLAIN PARTITIONS SELECT ... FROM tb WHERE ir_created_at >= '2011-11-01' AND ir_created_at < '2011-11-02';
-- 僅掃描 p201111 分區
按月匯出/匯入,配合 FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '\"' ESCAPED BY '\\\\' 標準格式。
| 引擎 | 2500 萬行導入耗時 | 備註 |
|---|---|---|
| MyISAM | ~4 小時 | 無事務日誌,批量寫入快 |
| InnoDB(預設參數) | ~32 小時 | 8 倍慢! |
| InnoDB(調優後) | ~3.5 小時 | 追平 MyISAM |
[mysqld]
# 1. 緩衝池:專用機設 70-80% 記憶體
innodb_buffer_pool_size = 16G
# 2. 重做日誌檔案:大檔案減少檢查點,提升寫入
innodb_log_file_size = 1G
innodb_log_files_in_group = 4
# 3. 重做日誌緩衝:大批量寫入時避免頻繁刷盤
innodb_log_buffer_size = 64M
# 4. 提交刷盤策略:2 = 寫入 OS 快取,每秒刷盤(極大提升寫入)
innodb_flush_log_at_trx_commit = 2
# 5. 繞過 OS 快取,直接 I/O(Linux/RAID/SSD 必開)
innodb_flush_method = O_DIRECT
# 6. 並行 I/O 執行緒(MySQL 5.6+)
innodb_read_io_threads = 16
innodb_write_io_threads = 16
innodb_io_capacity = 20000
innodb_io_capacity_max = 40000
#!/bin/bash
# migrate_parallel.sh - 按天並行遷移
PARTITION_DATES=("2011-11-01" "2011-11-02" ... "2012-12-31")
MAX_JOBS=4
for DATE in "${PARTITION_DATES[@]}"; do
# 控制併發數
while [ $(jobs -r | wc -l) -ge $MAX_JOBS ]; do sleep 5; done
(
OUT_DIR="/home/mysql/data/sinawb/${DATE//-/}"
mkdir -p "$OUT_DIR"
OUTFILE="${OUT_DIR}/${DATE}.txt"
# 1. 匯出(按天分區裁剪)
mysql -uroot -p${PASS} -e "
SELECT col1, col2, ..., DATE_FORMAT(ir_created_at,'%Y.%m.%d')
FROM TB_SINA_STATUS
WHERE ir_created_at >= '${DATE} 00:00:00'
AND ir_created_at < DATE_ADD('${DATE}', INTERVAL 1 DAY)
INTO OUTFILE '${OUTFILE}'
FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '\"' ESCAPED BY '\\\\'
LINES TERMINATED BY '\n';
"
# 2. 匯入
mysql -uroot -p${PASS} -e "
LOAD DATA LOCAL INFILE '${OUTFILE}'
IGNORE INTO TABLE NEW_TB_SINA_STATUS
CHARACTER SET UTF8
FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '\"' ESCAPED BY '\\\\'
LINES TERMINATED BY '\n';
"
echo "[$(date)] Partition ${DATE} done"
) &
done
wait
echo "All partitions migrated"
-- 1. Profiling 開啟與查看
SET profiling = 1;
-- 執行目標 SQL
SHOW PROFILES;
SHOW PROFILE CPU, BLOCK IO FOR Query 1;
-- 2. 即時狀態
SHOW STATUS LIKE 'Innodb%';
SHOW PROCESSLIST;
-- 3. 執行計畫
EXPLAIN PARTITIONS SELECT ...;
EXPLAIN ANALYZE SELECT ...; -- MySQL 8.0.18+
SELECT COUNT(*) FROM old_tb PARTITION (p...) vs new_tb 同條件。CHECKSUM TABLE 或應用層 MD5 比對關鍵欄位。DATE(ir_created_at) = new_date_col 全表驗證。SHOW CREATE TABLE 雙向比對。MAX_JOBS 視 CPU 核心、磁碟 IOPS、innodb_io_capacity 調整,通常 4-8 為宜。LOAD DATA ... IGNORE 可跳過主鍵衝突,配合冪等重跑機制保證最終一致性。