面對億級資料量,單表寫入/查詢效能瓶頸明顯。作者實踐 CRC32 雜湊分表 100 張 + MERGE 引擎統一視圖 方案,詳細記錄建表腳本、分表路由函數、MERGE 視圖建立與應用層適配要點。
$sql = "CREATE TABLE `code_%d` (
`full_code` CHAR(10) NOT NULL,
`create_time` INT UNSIGNED NOT NULL,
PRIMARY KEY (`full_code`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8";
for ($i = 0; $i <= 99; $i++) {
mysql_query(sprintf($sql, $i));
}
full_code 為 CHAR(10),固定長度利於分表雜湊計算。function getHashTable($prefix, $code, $shards = 100) {
$hash = sprintf("%u", crc32($code)); // 無符號整數
$shardId = intval(fmod($hash, $shards)); // 取模分片
return $prefix . '_' . $shardId; // 如 code_42
}
// 使用示例
$tableName = getHashTable('code', $fullCode);
$sql = "INSERT INTO `$tableName` (full_code, create_time) VALUES ('$fullCode', $now)";
mysql_query($sql);
crc32() 速度極快、分佈均勻、跨語言一致(PHP/Java/Python/Go 同算法)。sprintf("%u") 確保無符號,避免負數導致模運算異常。fmod() 處理大整數取模精確。CREATE TABLE IF NOT EXISTS `code` (
`full_code` CHAR(10) NOT NULL,
`create_time` INT UNSIGNED NOT NULL,
INDEX (`full_code`)
) ENGINE=MERGE UNION=(code_0,code_1,code_2,...,code_99) INSERT_METHOD=LAST;
ENGINE=MERGE:邏輯視圖,**不儲存資料**,查詢時自動路由至子表。UNION=(...):列舉所有 100 張子表名稱。INSERT_METHOD=LAST:INSERT INTO code ... 導向最後一張子表(code_99),**實際應用應禁用視圖寫入,改用路由函數寫入具體分表**。| 查詢類型 | SQL 示例 | 效能特徵 |
|---|---|---|
| 主鍵精確查詢 | SELECT * FROM code_42 WHERE full_code='ABC123' | 單表索引查找,極快 |
| 路由函數指定查詢 | 應用層計算表名 → 直查分表 | 零開銷,推薦寫入/點查 |
| 全表掃描/聚合 | SELECT COUNT(*) FROM code | MERGE 引擎並行掃描 100 表,較單表快 |
| 跨分頁排序 | SELECT * FROM code ORDER BY create_time DESC LIMIT 10 | 需應用層合併排序,MERGE 不支援跨表 ORDER BY |
$shards=200,**歷史資料需遷移**(按新規則重新分表)。ketama 演算法,擴容時僅遷移 1/N 資料。MyCat、ShardingSphere、Vitess 透明化分表邏輯。pt-online-schema-change 批量)。INSERT_METHOD=LAST 易導致熱點寫入,**嚴禁應用直接寫入 MERGE 表**。full_code 滿足)。CRC32 分表 + MERGE 視圖是**低成本、原生 MySQL、無中間件**的分表入門方案。適合:
長期演進建議引入分庫分表中間件,實現透明化、線上擴容、分散式事務支援。