索引列大小太大。最大列大小为767个字节。关于在Laravel中导入现有数据库的信息(请仔细阅读,不要重复)

时间:2019-05-27 10:57:22

标签: mysql database laravel mariadb

请仔细阅读。这不是该主题的重复项: #1071 - Specified key was too long; max key length is 767 bytesHow to fix 1709 - Index column size too large. The maximum column size is 767 bytes. in mysql in XAMPP

我已经有一个基地。我得到这个错误。我的问题是如何纠正它,我尝试了一切。

首先我在我的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工作

2 个答案:

答案 0 :(得分:0)

您可以将配置文件中的innodb_large_prefix设置为ON。如mysql doc所说,这将设置索引键前缀最多3072个字节。

[mysqld]
innodb_large_prefix = 1

答案 1 :(得分:0)

这是XY problem

为什么?因为问题不在于无法满足索引的数据量,所以就是症状

真正的问题

真正的问题是如何停止重复的电子邮件条目。

尝试的解决方法

尝试的解决方案是在UNIQUE列上创建一个email索引。这是解决该问题的绝佳尝试,但例外-电子邮件可能异常大,索引长度会有所不同。有时可能是10个字节,有时是30个字节,有时是50个字节,有时是255个字节-有时不好

返回到绘图板

如果所有电子邮件都有固定长度怎么办?这是一个更容易解决的问题。您不必担心索引大小限制,只需确保它低于默认限制767字节即可。

更好的解决方案

我们不要为email字段编制索引。让我们创建另一列email_unique,并在其中存储电子邮件的哈希。然后,将哈希作为UNIQUE索引。

好处: -始终与 -始终在默认索引长度767字节内 -不用担心utf8

如何做到尽可能浪费空间

  • 选择一个哈希算法。 sha1很好,尽管您可以申请sha256。我将使用SHA-2算法的256位版本
  • 创建一个binary(32 field)。它将保留我们哈希函数的原始值。对于任何类型的电子邮件,它始终会得到修复
  • 我将使用触发器before createbefore 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接受用于索引的字节数。但是,这不是最佳解决方案,因为您可以快速填满内存并基本上浪费资源。您可能会超出新设置的限制。