t_group:1000 萬行,欄位 id, money, user_name, create_timeuser_name 僅 8 個 distinct 值,單列索引選擇性極低(基數 8),查詢常按 user_name 過濾user_name 拆分為 8 張子表 t_group_{user_name},提升查詢效能
DELIMITER $$
DROP PROCEDURE IF EXISTS `sp_split_table`$$
CREATE PROCEDURE `sp_split_table`()
BEGIN
DECLARE done INT DEFAULT 0;
DECLARE v_user_name VARCHAR(20) DEFAULT '';
DECLARE v_table_name VARCHAR(64) DEFAULT '';
-- 獲取所有 user_name
DECLARE cur1 CURSOR FOR SELECT user_name FROM t_group GROUP BY user_name;
DECLARE CONTINUE HANDLER FOR 1329 SET done = 1; -- NOT FOUND
OPEN cur1;
read_loop: WHILE done <> 1 DO
FETCH cur1 INTO v_user_name;
IF NOT done THEN
SET v_table_name = CONCAT('t_group_', v_user_name);
-- 1. 建立子表(複製結構含索引)
SET @stmt = CONCAT('CREATE TABLE ', v_table_name, ' LIKE t_group');
PREPARE s1 FROM @stmt; EXECUTE s1; DEALLOCATE PREPARE s1;
-- 2. 遷移數據
SET @stmt = CONCAT('INSERT INTO ', v_table_name, ' SELECT * FROM t_group WHERE user_name = ', QUOTE(v_user_name));
PREPARE s1 FROM @stmt; EXECUTE s1; DEALLOCATE PREPARE s1;
-- 可選:驗證行數
-- SELECT CONCAT(v_table_name, ': ', ROW_COUNT()) AS migrated;
END IF;
END WHILE;
CLOSE cur1;
SET @stmt = NULL;
END$$
DELIMITER ;
-- 執行
CALL sp_split_table();
QUOTE() 包裹,避免單引號注入CREATE TABLE ... LIKE src 保留索引、約束、預設值、引擎DECLARE CONTINUE HANDLER FOR 1329 SET done=1 (MySQL 錯誤碼 1329 = No data)
-- 分表前
mysql> SHOW INDEX FROM t_group;
-- idx_user_name 基數 8,選擇性極低
-- 分表後
mysql> SHOW TABLES LIKE 't_group_%';
+------------------------------+
| t_group_david | t_group_leo | ... (8 張表) |
-- 單表查詢
SELECT * FROM t_group_david WHERE money > 1000;
-- 掃描行數從 1000萬 降為 ~125萬,索引選擇性大幅提升
idx_user_name(基數 8)、idx_combination1 (user_name, money)(鬆散索引掃描)user_name 相關索引(已隱含在表名中),保留 PRIMARY KEY (id)、idx_money (money) 等業務索引user_name 路由到對應子表| 維度 | 分表 | 分區 | 分庫 |
|---|---|---|---|
| 實現層 | 應用/中間件 | 資料庫內核 | 架構層 |
| 透明度 | 應用感知 | 完全透明 | 應用/中間件感知 |
| 跨分區查詢 | 應用 UNION | 優化器自動裁剪 | 中間件聚合 |
| 維護複雜度 | 高(DDL 需逐表) | 低(ALTER TABLE ... REORGANIZE PARTITION) | 最高 |
| 適用版本 | 所有 | 5.1+ | 所有 |
id 衝突 → 用雪花算法/UUID/分庫序列user_name 數據量極大,需二次拆分(按時間/哈希)ANALYZE TABLE低基數欄位(如 user_name 8 個值)是分表理想鍵。存儲過程自動化分表可復用,**核心價值在於將「大表低選擇性索引」轉化為「小表高選擇性索引 + 應用路由」**。生產環境建議配合中間件或應用框架實現透明路由,而非硬編碼表名。