1. 程式人生 > 實用技巧 >[資料庫/MYSQL]#解決缺陷#設定Unique索引時:"[Err] 1071 - Specified key was too long; max key length is 767 bytes"

[資料庫/MYSQL]#解決缺陷#設定Unique索引時:"[Err] 1071 - Specified key was too long; max key length is 767 bytes"

1 問題復現

  • 原表結構:
CREATE TABLE `XX_TEMPERATURE` (
	`FLOW_ID` int(11) NOT NULL COMMENT '獨立的資料表或FTP唯一標識', -- 與上述其它表的欄位完全無關聯,屬自創ID
	`TABLE_FLOW_ID` varchar(512) COLLATE utf8_bin DEFAULT NULL COMMENT '表,元資料uniqueID',  -- 本次部落格的重點
  		-- MYSQL_127.0.0.1_3306_root_CJ_TESTDBDatabase^CJ_TEST|DBTable^Person
	`TEMPERATURE_VALUE` int(11) NOT NULL COMMENT '(表級)熱度值',  -- 應保證其值實時更新 
	PRIMARY KEY (`FLOW_ID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='熱度值表';
  • 現需求

對 TABLE_FLOW_ID 新增 Unique 索引

  • 正常做法:
ALTER TABLE `XX_TEMPERATURE` ADD CONSTRAINT UNIQUE_INDEX_FOR_TABLE_FLOW_ID_OF_TEMPERATURE_TABLE UNIQUE(`TABLE_FLOW_ID`);

然鵝,出現瞭如下錯誤:

[SQL]ALTER TABLE `XX_TEMPERATURE` ADD CONSTRAINT UNIQUE_INDEX_FOR_TABLE_FLOW_ID UNIQUE(`TABLE_FLOW_ID`);
[Err] 1071 - Specified key was too long; max key length is 767 bytes

2 解決方案

本質上,就是 VARCHAR(512) 512>256了,導致的失敗。(更深層原因待深究)

方案1: 縮短Unique索引欄位的長度

ALTER TABLE `XX_TEMPERATURE` MODIFY `TABLE_FLOW_ID` VARCHAR(255);

方案2: [配置] 系統變數 innodb_large_prefix / 系統變數 innodb_file_format / 表配置項 ROW_FORMAT

要解決 [Err] 1071 - Specified key was too long; max key length is 767 bytes這一缺陷,必須滿足如下3個條件:

系統變數 innodb_large_prefix = ON
系統變數 innodb_file_format = Barracuda
表配置項 ROW_FORMAT = DYNAMIC / COMPRESSED
  • step1 配置 系統變數 innodb_large_prefix
set global innodb_large_prefix=on;

相關知識延伸

 -- 系統變數 innodb_large_prefix : 不同版本,開閉情況不同 (MySQL 5.6.41和5.6.33 預設關閉 ; MySQL 5.7 預設開啟)
 ---- 如果啟用了系統變數innodb_large_prefix,則:對於使用DYNAMIC或COMPRESSED行格式的InnoDB表,索引鍵字首限制為3072位元組。
 ---- 如果禁用innodb_large_prefix,則:對於任何行格式的表,索引鍵字首限制為767位元組。
 -- 檢視 innodb_large_prefix
 show variables like '%innodb_large_prefix%';
 -- 設定 innodb_large_prefix -- on / off
 set global innodb_large_prefix=off; -- off
  • step2 配置 系統變數 innodb_file_format
set global innodb_file_format=Barracuda; 

相關知識延伸

 -- 檢視
 show variables like '%innodb_file_format%';-- innodb_file_format = Antelope / innodb_file_format_check = ON / innodb_file_format_max = Barracuda
 -- 設定 
 set global innodb_file_format=Antelope; 
  • step3 配置 表配置項 ROW_FORMAT
ALTER TABLE XX_TEMPERATUREROW_FORMAT = DYNAMIC; 

相關知識延伸

 -- 備註 
 ---- https://www.cnblogs.com/wilburxu/p/9435818.html
 ---- 只有在MYSAM 的資料庫引擎才支援屬性: FIXED
 ---- fixed--->dynamic: 這會導致CHAR變成VARCHAR
 ---- dynamic--->fixed: 這會導致VARCHAR變成CHAR
 -- 檢視
 SHOW TABLE STATUS LIKE "%XX_TEMPERATURE%"; -- ROW_FORMAT 欄位 : Compact [ DEFAULT / Compact / FIXED / DYNAMIC / COMPRESSED / ... ]
 -- 設定
 ALTER TABLE XX_TEMPERATUREROW_FORMAT = Compact; 

X 參考資料