代码之家  ›  专栏  ›  技术社区  ›  Daniel Viglione

使用并集utf8_unicode_ci限制索引列的VARCHAR长度的必要性

  •  0
  • Daniel Viglione  · 技术社区  · 7 年前

    我试图理解一个MySQL错误,它与Rails通过ActiveRecord迁移生成的一些默认值有关。鉴于此:

    rails generate migration AddDetailsToProducts supplier:index:references{polymorphic}
    
    class AddDetailsToProducts < ActiveRecord::Migration
      def change
        add_reference :products, :supplier, polymorphic: true, index: true, foreign_key: true
      end
    end
    

    参考文件将供应商类型和供应商id作为产品的外键添加到供应商主密钥中。外键是指一个表中引用另一个表中主键的字段(或字段集合)。它是一个键,用于将两个表链接在一起。

    CREATE TABLE products (
      PRIMARY KEY (id),
      FOREIGN KEY (supplier_id) REFERENCES suppliers(id)
      FOREIGN KEY (supplier_type) REFERENCES suppliers(id)
    )
    CREATE  INDEX `index_suppliers_on_supplier_type`  ON `suppliers` (`supplier_type`) 
    CREATE  INDEX `index_suppliers_on_supplier_id`  ON `suppliers` (`supplier_id`) 
    

    现在我收到了这样一个错误:

    指定的密钥太长;最大密钥长度为767字节:创建索引 index_suppliers_on_supplier_type suppliers ( supplier_type )

    所以我们得到的是一个supplier_类型的列,它是VARCHAR(255),我们试图在它上面建立一个索引。我使用的是utf8_unicode_ci结合。我的理解是每个字符使用1到3个字节。因此,即使对所有字符使用3个字节,最多256个字符,也就是256*3=768。超过一个字节。真的没有道理。解决方案真的只是为列添加一个最大字符大小的限制吗?我理解得对吗?

    因为当我这样做时,错误就会消失:

    class ChangeSuppliers < ActiveRecord::Migration
      def change
        change_column :suppliers, :supplier_type, :string, limit: 191
      end
    end
    
    1 回复  |  直到 7 年前
        1
  •  0
  •   danblack    7 年前

    排序只是顺序,真正的原因是字符集。 This answer 显示了一些变通方法。像你这样的指数限制也是有效的。

    rather and arbitrary choice 根据数据选择限制是最好的方法。