手机看片精品高清国产日韩,色先锋资源综合网,国产哺乳奶水91在线播放,乱伦小说亚洲色图欧洲电影

幫助中心 >  技術(shù)知識(shí)庫 >  云服務(wù)器 >  服務(wù)器教程 >  mysql索引過長Specialed key was too long的解決方法

mysql索引過長Specialed key was too long的解決方法

2025-01-07 08:42:15 4913

mysql索引過長Specialed key was too long的解決方法

 

歡迎來到藍(lán)隊(duì)云技術(shù)小課堂,每天分享一個(gè)技術(shù)小知識(shí)。

 

在創(chuàng)建要給表的時(shí)候遇到一個(gè)有意思的問題,提示Specified key was too long; max key length is 767 bytes,從描述上來看,是Key太長,超過了指定的 767字節(jié)限制。通常出現(xiàn)在嘗試創(chuàng)建一個(gè)過長的唯一鍵(UNIQUE KEY)或主鍵(PRIMARY KEY)時(shí)。MySQL對(duì)于InnoDB存儲(chǔ)引擎有一個(gè)索引鍵長度的限制,這個(gè)限制基于字符集的不同而不同。

 

下面是產(chǎn)生問題的表結(jié)構(gòu)

 

CREATE TABLE `test_table` (

  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,

  `name` varchar(1000) NOT NULL DEFAULT '',

  `link` varchar(1000) NOT NULL DEFAULT '',

  PRIMARY KEY (`id`),

  KEY `name` (`name`)

) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4;

 

在使用utf8字符集時(shí),每個(gè)字符可能占用3個(gè)字節(jié),那么對(duì)于innodb表,索引鍵的最大長度大約為1000個(gè)字符左右(因?yàn)?072 / 3 ≈ 1024)。若字符集是utf8mb4,每個(gè)字符可能占用4個(gè)字節(jié),所以最大長度會(huì)進(jìn)一步減少到768個(gè)字符左右(3072 / 4 = 768)

 

uf8mb4字符集:

要在 Mysql 中保存 4 字節(jié)長度的 UTF-8 字符,需要使用 utf8mb4 字符集(mb4就是most bytes 4的意思,專門用來兼容四字節(jié)的unicode),但只有 5.5.3 版本以后的才支持。

為了獲取更好的兼容性,應(yīng)該總是使用 utf8mb4 而非 utf8. 對(duì)于 CHAR 類型數(shù)據(jù),utf8mb4 會(huì)多消耗一些空間,根據(jù) Mysql 官方建議,使用 VARCHAR 替代 CHAR。其實(shí),utf8mb4是utf8的超集,理論上原來使用utf8,然后將字符集修改為utf8mb4,也會(huì)不會(huì)對(duì)已有的utf8編碼讀取產(chǎn)生任何問題。當(dāng)然,為了節(jié)省空間一般情況下使用utf8也就夠了。

 

對(duì)于name,我們?cè)O(shè)置長度為1000可變字符,因?yàn)椴捎胾tf8mb4編碼, 所以它的大小就變成了 1000 * 4 > 767

所以再不修改其他配置的前提下,varchar的長度大小應(yīng)該是 767 / 4 = 191

有興趣的同學(xué)可以測試下,分別指定name大小為191, 192時(shí),是不是前面的可以創(chuàng)建表成功,后面的創(chuàng)建表失敗,并提示錯(cuò)誤Specified key was too long; max key length is 767 bytes

 

解決辦法

使用innodb引擎

啟用innodb_large_prefix選項(xiàng),修改約束擴(kuò)展至3072字節(jié)

重新創(chuàng)建數(shù)據(jù)庫

my.cnf配置

 

set global innodb_large_prefix=on;

set global innodb_file_per_table=on;

set global innodb_file_format=BARRACUDA;

set global innodb_file_format_max=BARRACUDA;

上面這個(gè)3072字節(jié)的得出原因如下

 

我們知道InnoDB一個(gè)page的默認(rèn)大小是16k。由于是Btree組織,要求葉子節(jié)點(diǎn)上一個(gè)page至少要包含兩條記錄(否則就退化鏈表了)。

所以一個(gè)記錄最多不能超過8k。又由于InnoDB的聚簇索引結(jié)構(gòu),一個(gè)二級(jí)索引要包含主鍵索引,因此每個(gè)單個(gè)索引不能超過4k (極端情況,pk和某個(gè)二級(jí)索引都達(dá)到這個(gè)限制)。

由于需要預(yù)留和輔助空間,扣掉后不能超過3500,取個(gè)“整數(shù)”就是(1024*3)。

 

在創(chuàng)建表的時(shí)候,加上 row_format=DYNAMIC

 

CREATE TABLE `test_table` (

  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,

  `name` varchar(255) NOT NULL DEFAULT '',

  `link` varchar(255) NOT NULL DEFAULT '',

  PRIMARY KEY (`id`),

  KEY `name` (`name`)

) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 row_format=DYNAMIC;

 

代碼解讀

這個(gè)參數(shù)的作用如下

MySQL 索引只支持767個(gè)字節(jié),utf8mb4 每個(gè)字符占用4個(gè)字節(jié),所以索引最大長度只能為191個(gè)字符,即varchar(191),若想要使用更大的字段,mysql需要設(shè)置成支持?jǐn)?shù)據(jù)壓縮,并且修改表屬性 row_format ={DYNAMIC|COMPRESSED}

 

藍(lán)隊(duì)云官網(wǎng)上擁有完善的技術(shù)支持庫可供參考,大家可自行查閱,更多技術(shù)問題,可以直接咨詢。同時(shí),藍(lán)隊(duì)云整理了運(yùn)維必備的工具包免費(fèi)分享給大家使用,需要的朋友可以直接咨詢。

更多技術(shù)知識(shí),藍(lán)隊(duì)云期待與你一起探索。


提交成功!非常感謝您的反饋,我們會(huì)繼續(xù)努力做到更好!

這條文檔是否有幫助解決問題?

非常抱歉未能幫助到您。為了給您提供更好的服務(wù),我們很需要您進(jìn)一步的反饋信息:

在文檔使用中是否遇到以下問題: