大家應該知道innodb單列索引長度不能超過767bytes,聯合索引還有乙個限制是長度不能超過3072。
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
keywas too long;
maxkey
length
is3072 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的大小:
這樣,在建立索引時就會限制使用的每個列的最大長度。如上的例子中,在建立聯合索引時,最多使用列flow_exec_id中前100個字元建立索引,最多使用another_column中前
50個字元建立索引。這樣子,就可以避免索引長度過大的問題。
最後,我想說一句。我們在設計資料庫時,最好不要在乙個可能包含很長字串的列上建立索引,尤其是當這個列中的字串都很長時。如果在這類列上建立了索引,那麼在建立索引時以及根據索引查詢時,都會浪費很多時間在計算和儲存上。有經驗的設計人員應該不會這樣設計資料庫。
作者簡介:屈世超,對高併發系統設計開發感興趣,現專注於大資料開發工作。曾任職小公尺科技公司服務端後台開發工程師,現擔任everstring資料平台組高階開發工程師。
Mysql (InnoDB引擎)聚集索引和輔助索引
innodb儲存引擎表是索引組織表,即按照主鍵的順序儲存資料。聚集索引 clustered index 就是按照每張表的主鍵構造一棵b 樹,樹中的葉子節點存放著表中的行記錄資料,因此,也將聚集索引的葉子節點稱為資料頁 非葉子節點中存放著僅僅是鍵值和指向葉子節點的偏移量。每個葉子節點 資料頁 都通過乙...
mysql InnoDB引擎索引超過長度限制
組合索引長度之和大於 767 bytes並無影響,當有某個字段定義長度大於 767 bytes 1000 3 時,僅產生告警,但不影響建立,超長欄位會取前 255 字元作為字首索引,並且組合索引中欄位出現的順序並無關係。為什麼3072innodb乙個page的預設大小是 16 k。由於是btree組...
MySQL InnoDB引擎B 樹索引簡單整理說明
本文出處 mysql中的innodb引擎表索引型別有一下幾種 以下所說的索引,沒有特殊說明,均指innodb引擎表索引。0 secondary index,二級索引,1 clustered index,聚集索引 2 unique index,唯一索引 3 primary index,主鍵索引 32 ...