【问题标题】:Key longer than 255 chars in a UTF8 mysql databaseUTF8 mysql 数据库中的密钥长度超过 255 个字符
【发布时间】:2015-09-07 06:20:23
【问题描述】:

我需要在现有的 Django/South/MySQL 应用程序中存储超过 255 个字符的 URL。这些 URL 用作外键。问题是排序规则是 UTF8,所以如果我将 URLField 的 max_length 增加到 512,我会收到以下错误:

'Specified key was too long; max key length is 767 bytes'

我猜原因是在 UTF8 中,每个字符可能有 3 个字节长,所以即使只有 256 个字符,我也可以超过限制。

由于 URL 应该只包含 ASCII 字符,因此我尝试在(数据)迁移中将特定表的排序规则更改为 ASCII,并且似乎效果很好:迁移后,我可以成功地将 max_length 更改为 512后续架构迁移并存储更长的 URL。

但是,在引导数据库时,我遇到的问题是它尝试设置数据库而不进行迁移:

syncdb --all
migrate --fake

syncdb,当然会失败,因为它再次尝试创建太长的外键(未运行调整数据库排序规则的迁移)。

如果我在没有 --all 的情况下同步db,(然后在没有 --fake 的情况下运行迁移),它会失败,说某些身份验证表不存在。

知道增加 max_length 限制的正确方法吗?

【问题讨论】:

    标签: mysql django utf-8 django-south


    【解决方案1】:

    我采取的一种侵入性较小且不太干净的方法是:

    • 使用indexes with prefix size。这只能在迁移中使用原始 SQL 语句来完成。
    • 由于设置新数据库时通常不会运行迁移,因此我做了一个创建索引的管理命令,该命令必须在syncdb和迁移之后运行:

      ./manage.py syncdb --all
      ./manage.py migrate --fake
      ./manage.py create_indexes
      

    myapp/management/commands/create_indexes.py 是一个管理命令,它运行原始 SQL 命令来创建带前缀的索引。

    【讨论】:

      【解决方案2】:

      最好的,也可能是唯一的解决方案:根本不要使用 url 作为外键。

      将 url 放入带有 surrogate key 的表中(例如,自动递增整数)。使用该键作为外键,只需在 url 列上放置一个唯一索引以防止重复 url。

      【讨论】:

      • 这绝对是一个更好的设计。如果您考虑执行连接所需的总计算量,请考虑存储 768 个字符的字符串与整数所需的位数;然后想想计算机必须做些什么来匹配两者之间的相等性:dev.mysql.com/doc/refman/5.7/en/storage-requirements.html
      • 非常感谢分享。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-06-01
      • 1970-01-01
      • 2019-05-05
      • 1970-01-01
      • 2011-03-02
      相关资源
      最近更新 更多