單表超 1000 萬行,採集程序單條 INSERT 耗時約 100ms,寫入吞吐極低,嚴重拖慢採集管道。
[mysqld]
bulk_insert_buffer_size = 100M # 默認 8M
INSERT ... SELECT、LOAD DATA)innodb_buffer_pool_size 管理寫入緩衝,此參數不生效INSERT DELAYED INTO table VALUES (...);
-- 單條 100ms → 批量 1000 條/次 約 50ms/批 → 20x 提升
INSERT INTO tbl (col1, col2) VALUES
('a1','b1'), ('a2','b2'), ..., ('a1000','b1000');
max_allowed_packet(默認 4MB/64MB)控制 SQL 長度LOAD DATA INFILE '/path/data.csv'
INTO TABLE tbl
FIELDS TERMINATED BY ',' ENCLOSED BY '"'
LINES TERMINATED BY '\n'
IGNORE 1 LINES
(col1, col2);
secure_file_priv 允許路徑、文件在服務器本地、表無外鍵/觸發器SET unique_checks=0; SET foreign_key_checks=0; SET autocommit=0; 導入後恢復[mysqld]
# 核心緩衝池:物理內存 60-80%
innodb_buffer_pool_size = 16G
# Redo Log:大事務不阻塞,建議 1-4GB 總大小
innodb_log_file_size = 1G
innodb_log_files_in_group = 4
# 刷盤策略:批量導入時可暫時放寬為 2(僅崩潰丟失 1s 數據)
innodb_flush_log_at_trx_commit = 2
# 讀寫線程
innodb_read_io_threads = 8
innodb_write_io_threads = 8
# 自適應哈希索引、插入緩衝
innodb_adaptive_hash_index = ON
innodb_change_buffer_max_size = 50
import pymysql
from contextlib import contextmanager
@contextmanager
def batch_insert(conn, table, columns, batch_size=1000):
"""批量插入上下文管理器"""
buffer = []
col_str = ','.join(f'`{c}`' for c in columns)
ph = ','.join(['%s'] * len(columns))
sql = f"INSERT INTO `{table}` ({col_str}) VALUES ({ph})"
def flush():
if buffer:
with conn.cursor() as cur:
cur.executemany(sql, buffer)
conn.commit()
buffer.clear()
try:
def add_row(row):
buffer.append(tuple(row[c] for c in columns))
if len(buffer) >= batch_size:
flush()
yield add_row
finally:
flush()
# 使用示例
with pymysql.connect(...) as conn:
with batch_insert(conn, 'metrics', ['host', 'metric', 'value', 'ts']) as inserter:
for data in fetch_metrics():
inserter(data)
文中提到「成熟 CMS 不建議修改」,原因在於:
採集/日志/監控類寫多讀少、無強關聯業務 適合激進優化;用戶核心業務表 廉用緩存、異步隊列、分庫分表等架構級方案。
| 層級 | 手段 | 適用引擎 | 提升幅度 | 風險 |
|---|---|---|---|---|
| SQL 語句 | 批量多值 INSERT | 全引擎 | 10-50x | 低 |
| 數據載入 | LOAD DATA INFILE | 全引擎 | 50-200x | 中(需文件權限) |
| 引擎參數 | innodb_buffer_pool, log_file, flush_log | InnoDB | 2-5x | 低(動態調整) |
| 會話設置 | 關閉 unique_checks, FK_checks, autocommit | InnoDB | 2-3x | 中(導入後必須恢復) |
| 架構級 | 分區表、分庫分表、異步寫入隊列 | 全引擎 | 水平擴展 | 高(代碼重構) |
對於文中採集場景,**批量 INSERT + 適度調大 InnoDB 緩衝池/Redo Log** 是性價比最高、風險最低的組合拳。