[轉]MySQL InnoDB引擎索引長度受限怎麼辦

mysql> CREATE TABLE `tb` (
-> `a` varchar(255) DEFAULT NULL,
-> `b` varchar(255) DEFAULT NULL,
-> `c` varchar(255) DEFAULT NULL,
-> `d` varchar(255) DEFAULT NULL,
-> `e` varchar(255) DEFAULT NULL,
-> KEY `a` (`a`,`b`,`c`,`d`,`e`)
-> ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
ERROR 1071 (42000): Specified key was too long; max key length is 3072 bytes
能夠看到,因爲每一個字段佔用255*3, 所以這個索引的大小是3825>3072,報錯。
爲何3072
咱們知道InnoDB一個page的默認大小是16k。因爲是Btree組織,要求葉子節點上一個page至少要包含兩條記錄(不然就退化鏈表了)。
因此一個記錄最多不能超過8k。
又因爲InnoDB的聚簇索引結構,一個二級索引要包含主鍵索引,所以每一個單個索引不能超過4k (極端狀況,pk和某個二級索引都達到這個限制)。
因爲須要預留和輔助空間,扣掉後不能超過3500,取個「整數」就是(1024*3)。
單列索引限制

上面有提到單列索引限制767,原由是256×3-1。這個3是字符最大佔用空間(utf8)。可是在5.5之後,開始支持4個字節的uutf8。255×4>767, 因而增長了一個參數叫作 innodb_large_prefix。
這個參數默認值是OFF。當改成ON時,容許列索引最大達到3072。
能夠看到默認行爲是建表成功,報一個warning,而且將長度階段爲255。
注意要生效須要加row_format=compressed或者dynamic 。
若是確實須要在單個很大的列上建立索引,或者須要在多個很大的列上建立聯合索引,而又超過了索引的長度限制,解決辦法是在建索引時限制索引prefix的大小:
例如:create index yarn_app_result_i4 on yarn_app_result (flow_exec_id(100), another_column(50));
這樣,在建立索引時就會限制使用的每一個列的最大長度。如上的例子中,在建立聯合索引時,最多使用列flow_exec_id中前100個字符建立索引,最多使用another_column中前
50個字符建立索引。這樣子,就能夠避免索引長度過大的問題。

最後,我想說一句。咱們在設計數據庫時,最好不要在一個可能包含很長字符串的列上建立索引,尤爲是當這個列中的字符串都很長時。若是在這類列上建立了索引,那麼在建立索引時以及根據索引查詢時,都會浪費不少時間在計算和存儲上。有經驗的設計人員應該不會這樣設計數據庫。mysql

相關文章
相關標籤/搜索