漫谈MySQL索引与字段儿长度的关系
在數據庫開發中,索引是優化查詢性能的重要手段,本文是對使用MySQL?5.6.28進行索引優化時遇到的問題一個總結,目的是為了加深對索引長度和字段長度的理解,理清這兩個長度的關系,本文件均使用InnoDB存儲引擎、utf8字符集、索引方法為btree。
在使用MySQL時常用的數據類型有int、bigint、char、varchar、date、datetime、timestamp、float、double,每種類型和長度見下表:
| 數據類型 | 長度(byte) |
| int | 4 |
| bigint | 8 |
| char(n) | n表示字符數,字節數為n*3,n<=255 |
| varchar(n) | n表示字符數,字節數為n*3,n<=21845 |
| date | 3 |
| datetime | 8 |
| timestamp | 4 |
| float | 4 |
| double | 8 |
在MySQL中為表建立索引時經常會遇到“Error : Specified key was too long; max key length is 767 bytes”和“Error : Duplicate key name ind_composite_3072”錯誤,767和3072的由來參考官方文檔或《關于InnoDB索引長度限制的tips》。這兩個錯誤都和MySQL對索引長度的默認設置有關,可通過設置innodb_large_prefix,修改767為3072。由于MySQL使用前綴索引,所謂前綴索引,指的是只用字段的前n個字符建立索引。除text、blob在建索引時必須要指定前綴長度外,大部分類型是不需要指定長度的,指定前綴的方法見后面的示例。
下面通過具體示例來說明字段長度與索引長度的關系,為了測試建立"index_test"表,SQL如下:
CREATE TABLE `index_test` (
`id` int NOT NULL,
`num` bigint,
`achar` char(50),
`avarchar` varchar(2000),
`adate` date,
`adatetime` datetime,
PRIMARY KEY (`id`)
) ENGINE INNODB DEFAULT CHARACTER SET utf8 COMMENT='測試索引長度與字段長度的關系';
接下來為表“index_test”在“avarchar”字段上增加一個索引,創建索引時不指定索引前綴的長度,SQL如下:
ALTER TABLE `index_test` ADD INDEX `ind_single_varchar` (avarchar) COMMENT '單一varchar字段的索引,不指定索引前綴的長度';執行上面的SQL時,MySQL給出了錯誤提示“Error : Specified key was too long; max key length is 767 bytes”,這句話的意思是索引的最大長度為767字節(byte),而“index_test”的“avarchar”的長度為2000字符,由于使用的是utf8字條集,一個字符占3個字節,長度為2000*3=6000字節,所以創建失敗。接下來我們為索引指寫前綴長度,索引前綴的長度單位為字符,SQL如下:
ALTER TABLE `index_test` ADD INDEX `ind_single_varchar_pre` (avarchar(255)) COMMENT '單一varchar字段的索引,指定索引前綴長度為255字符';?“avarchar(255)”是MySQL創建索引語法的一部分,形式為“字段名(索引前綴長度)”,單位為字符,255*3=765<767,所以上面的語句能夠正常執行。實際使用中text、blob使用的不多,所以“Error : Specified key was too long; max key length is 767 bytes”通常在對varchar類型字段建索引出現。
在對單個字段創建索引時,主要的限制是字段長度,如果字段長度不超過767字節,不會出現問題。但復合索引的情況與單字段索引有所不同。復合索引中除了單字段長度不能超過767字節外,索引中所有字段長度的總合不能超過3072字節。
為了進一步測試復合索引與字段長度的關系,讓我們增加幾個varchar類型的字段,SQL如下:
ALTER TABLE `index_test` ADD COLUMN `bvarchar` VARCHAR(255),
ADD COLUMN `cvarchar` VARCHAR(255),
ADD COLUMN `dvarchar` VARCHAR(255),
ADD COLUMN `evarchar` VARCHAR(255);
接下來為“index_test”增加一個復合索引,創建索引時不指定索引前綴的長度,SQL如下:
ALTER TABLE `index_test` ADD INDEX `ind_composite` (`id`,`num`,`achar`,`adate`,`adatetime`,`avarchar`)
COMMENT '不指定前綴長度的復合索引';
由于“avarchar”的長度為2000字符,2000*3>767,這違反了MySQL的約束,如期給出錯誤提示“Error : Specified key was too long; max key length is 767 bytes”。接下來為“avarchar”指定索引的前綴長度,SQL如下:
ALTER TABLE `index_test` ADD INDEX `ind_composite_pre` (`id`,`num`,`achar`,`adate`,`adatetime`,`avarchar`(255))
COMMENT '指定avarchar前255個字符用于索引';
由于指定了前255個字符用于索引,所以上面的語句得以正常執行。
通過上面的例子我們驗證了在復合索引中,對單個字段的約束條件,這一點和單字段索引是一樣的。下面的例子將用于驗證MySQL對復合索引總長度為3072字節的限制。用下面的SQL為“index_test”表創建復合索引,如下:
ALTER TABLE `index_test` ADD INDEX `ind_composite_3072` (`bvarchar`,`cvarchar`,`dvarchar`,`evarchar`,`num`,`adatetime`)
COMMENT '復合索引,總長度不能超過<=3072字節';
由于“bvarchar”、“cvarchar”、“dvarchar”、“evarchar”長度均為255字符,即255*3=3060字節,“num”、“adatetime”為8字節,所以這個索引的總長度為3060+8+8=3076字節>3072,執行上面語句時MySQL會給出錯誤提示“Error : Duplicate key name ind_composite_3072”。
通過上面一系列的試驗,我們明確知道MySQL創建索引時,單字段索引的字段長度不能超過767字節,超過時需要指定索引前綴;創建復合索引時,單字段長度不能超過767字節,且索引中所有字段的總長度不能超過3072字節,違反這些約束時需要刪減字段或是為長度較大的字段指定索引前綴。在MySQL 5.6.28中,字符類型的長度指的是字符數,而不是字節數,每個字符占用的字節數和使用的字符集相關。
來源:https://blog.csdn.net/houyefeng/article/details/81628781
總結
以上是生活随笔為你收集整理的漫谈MySQL索引与字段儿长度的关系的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 谈谈读书自由与财富自由
- 下一篇: 不接催款电话的后果 会影响个人征信