执行以下命令时:
ALTER TABLE `mytable` ADD UNIQUE (
`column1` ,
`column2`
);
我得到了这个错误信息:
#1071 - Specified key was too long; max key length is 767 bytes
columnn1和column2的信息:
column1 varchar(20) utf8_general_ci
column2 varchar(500) utf8_general_ci
我认为varchar(20)只需要21个字节,而varchar(500)只需要501个字节。所以总字节数是522,小于767。为什么我得到了错误消息?
#1071 - Specified key was too long; max key length is 767 bytes
这个问题
MySQL中有最大键长度限制。
InnoDB -最大密钥长度为1536字节(8kb页面大小)和768字节(4kb页面大小)(来源:Dev.MySQL.com)
MyISAM -最大密钥长度是1000字节(来源Dev.MySQL.com)。
这些都是以字节为单位计算的!因此,一个UTF-8字符可能需要一个以上的字节才能存储到密钥中。
因此,你只有两个直接的解决方案:
只索引文本类型的前n个字符。
创建一个全文搜索-所有内容都可以在文本中搜索,以一种类似ElasticSearch的方式
索引文本类型的前N个字符
如果您正在创建一个表,请使用以下语法来索引某些字段的前255个字符:KEY sometextkey (SomeText(255))。像这样:
CREATE TABLE `MyTable` (
`id` int(11) NOT NULL auto_increment,
`SomeText` TEXT NOT NULL,
PRIMARY KEY (`id`),
KEY `sometextkey` (`SomeText`(255))
);
如果你已经有了这个表,那么你可以用add unique (ConfigValue(20));为一个字段添加一个唯一键。像这样:
ALTER TABLE
MyTable
ADD UNIQUE(`ConfigValue`(20));
如果字段名不是保留的MySQL关键字,则在字段名周围不需要反引号(' ' ')。
创建全文搜索
全文搜索将允许您搜索文本字段的全部值。如果你使用自然语言模式,它会进行全词匹配,如果你使用其他模式之一,它会进行部分词匹配。查看更多关于全文本的选项:Dev.MySQL.com
创建您的文本表,并添加全文索引…
ALTER TABLE
MyTable
ADD FULLTEXT INDEX
`SomeTextKey` (`SomeTextField` DESC);
然后像这样搜索你的桌子……
SELECT
MyTable.id, MyTable.Title,
MATCH
(MyTable.Text)
AGAINST
('foobar' IN NATURAL LANGUAGE MODE) AS score
FROM
MyTable
HAVING
score > 0
ORDER BY
score DESC;
Laravel框架解决方案
根据Laravel 5.4。*文档;你必须在app/Providers/AppServiceProvider.php文件的引导方法中设置默认字符串长度,如下所示:
use Illuminate\Support\Facades\Schema;
public function boot()
{
Schema::defaultStringLength(191);
}
Laravel 5.4对这个修复的解释。*文档:
Laravel uses the utf8mb4 character set by default, which includes support for storing "emojis" in the database. If you are running a version of MySQL older than the 5.7.7 release or MariaDB older than the 10.2.2 release, you may need to manually configure the default string length generated by migrations in order for MySQL to create indexes for them. You may configure this by calling the Schema::defaultStringLength method within your AppServiceProvider.
Alternatively, you may enable the innodb_large_prefix option for your
database. Refer to your database's documentation for instructions on
how to properly enable this option.
在MySQL 5.6(以及之前的版本)中,767字节是InnoDB表的前缀限制。MyISAM表有1000字节长。在MySQL版本5.7(及以上)中,此限制已增加到3072字节。
您还必须注意,如果在utf8mb4编码的大char或varchar字段上设置索引,则必须将最大索引前缀长度767字节(或3072字节)除以4,结果为191。这是因为utf8mb4字符的最大长度是4个字节。对于utf8字符,它将是三个字节,导致最大索引前缀长度为255(或减去空结束符,254个字符)。
一个选择是在VARCHAR字段上设置下限。
另一种选择(根据对这个问题的响应)是获取列的子集,而不是整个数量,即:
ALTER TABLE `mytable` ADD UNIQUE ( column1(15), column2(200) );
根据需要进行调整以获得要应用的键,但我想知道是否值得检查关于这个实体的数据模型,看看是否有可能进行改进,从而允许您在不触及MySQL限制的情况下实现预期的业务规则。