mysql - 索引列大小太大。最大列大小为 767 字节。在 Laravel 中导入现有数据库(仔细阅读,不要重复)
问题描述
请仔细阅读。这不是主题的重复: #1071 - 指定的密钥太长;最大密钥长度为 767 字节, 如何修复 1709 - 索引列大小太大。最大列大小为 767 字节。在 XAMPP 中的 mysql 中
我已经有一个现有的基地。我得到这个错误。我的问题是如何纠正它,我尝试了一切。
首先我在我的 database.php 中设置了这段代码
'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
我设置后:
Schema::defaultStringLength(191);
我总是收到错误消息:
索引列大小太大。最大列大小为 767 字节。
我的导入第一次在这里爆发:
CREATE TABLE `admins` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`email` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`password` varchar(60) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`created_at` timestamp NULL DEFAULT NULL,
`updated_at` timestamp NULL DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `admins_email_unique` (`email`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8mb4
COLLATE=utf8mb4_unicode_ci
这是连续5张桌子,我还有40张。出于这个原因,我无法更改现有表。
问题,如何解决这个问题?我使用 mariaDB 和 xampp。我的问题与上述问题之间的区别在于我导入了现有表并且无法更改数据。我也在 Laravel 工作
解决方案
这是一个XY 问题
为什么?因为问题不在于不符合索引的数据量,所以这就是症状。
真正的问题
真正的问题是如何停止重复的电子邮件条目。
尝试的解决方案
尝试的解决方案是在列上创建UNIQUE
索引。email
这是解决问题的一个很好的尝试,除了 - 电子邮件可能非常大,您的索引长度会有所不同。有时它可能是 10 个字节,有时是 30,有时是 50.. 有时是 255 - 这不好。
回到绘图板
如果所有电子邮件都有固定长度怎么办?这是一个更容易解决的问题。您不必担心索引大小限制,您只需确保它低于 767 字节的默认限制。
更好的解决方案
我们不要索引该email
字段。让我们创建另一个列,并将电子邮件的哈希email_unique
存储在那里。然后,使哈希成为索引。UNIQUE
好处: - 总是固定的 - 总是在 767 字节的默认索引长度内 - 不用担心 utf8
如何做到尽可能少地浪费空间
- 选择哈希算法。
sha1
完全没问题,虽然你可以去sha256
。我将使用 256 位版本的SHA-2
算法 - 创建一个
binary(32 field)
. 它将保存我们散列函数的原始值。对于任何类型的电子邮件,它将始终被修复 - 我将使用触发器,
before create
并before update
维护散列的值,因此我不必担心我的语言逻辑中的它。
添加二进制列
ALTER TABLE admins ADD email_hash BINARY(32) AFTER email;
添加前插入触发器
DELIMITER $$
CREATE TRIGGER `admins_before_insert` BEFORE INSERT
ON admins
FOR EACH ROW BEGIN
SET NEW.email_hash = UNHEX(SHA2(NEW.email, 256)); -- this creates a binary representation of a sha-256 hashed email column
END$$
DELIMITER ;
更新前添加触发器
DELIMITER $$
CREATE TRIGGER `admins_before_insert` BEFORE UPDATE
ON admins
FOR EACH ROW BEGIN
SET NEW.email_hash = UNHEX(SHA2(NEW.email, 256)); -- this creates a binary representation of a sha-256 hashed email column
END$$
DELIMITER ;
最后的话
我添加了触发器示例代码,但我没有测试它。这个想法是能够添加和更新电子邮件,并让 MySQL 告诉你是否有重复。有些人不喜欢使用触发器。这就是为什么带有触发器的步骤是可选的,以及如果您更喜欢该路线,如何实现效果的示例。
当然,您可以增加 MySQL 将接受的用于索引的字节数。但是,这不是最佳解决方案,因为您可以快速填满内存并基本上浪费资源。下线,你可能会超过新设定的限制。
推荐阅读
- javascript - Qualtrics:为什么当我返回到它所在的页面时 jQuery datepicker 插件没有重新初始化?
- spring-boot - 可以从 Spring Boot 应用程序中的 Redis 缓存中提取 yaml 键值吗?
- java - 一次在触摸监听器上读取 ACTION_MOVE
- c - 每次我尝试编译这段代码时,它都会给我这个警告:返回类型默认为 'int' [-Wimplicit-int] BuildMaxHeap(int A[], int n) {
- discord.js - 在执行之前检查函数是否会导致错误
- javascript - 我可以创建一个共享的 html 文件来保存我的导航吗?
- google-api - 如何为桌面创建 OAuth 2.0 客户端 ID?
- python - 无法从 Docker 中的 Celery 访问 Django 模型
- c# - 使用 WeakEventManager,隐藏实际事件 - 重访
- pywin32 - pywin32 安装是否会导致注册表设置发生任何可能影响 MAPI 的更改