Необходимость ограничения длины VARCHAR для индексированных столбцов с использованием коалиции utf8_unicode_ci

0

Я пытаюсь понять ошибку 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

Так, что это делает? Во-первых, давайте посмотрим на полиморфизм. Polymorphic создаст столбцы поставщика VARCHAR (255) и столбца поставщика INT в продуктах. Я считаю, что VARCHAR установлен на 256 символов, так как ранние версии MySQL не поддерживали больше. Но помните, что столбцы VARCHAR в базе данных имеют переменную длину, поэтому в VARCHAR (255) по сравнению с VARCHAR (20) нет преимущества хранения в десятизначном значении.

При добавлении ссылки в качестве внешних ключей продуктов к первичному ключу поставщиков добавляются supplier_type и supplier_id. FOREIGN KEY - это поле (или набор полей) в одной таблице, которое ссылается на PRIMARY KEY в другой таблице. Это ключ, используемый для связи двух таблиц.

Так что я думаю, что add_reference делает что-то вроде этого:

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 байт: CREATE INDEX index_suppliers_on_supplier_type ON suppliers (supplier_type)

Итак, у нас есть столбец supplier_type, который является 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
Теги:
database

1 ответ

0

Сопоставление - это просто порядок, настоящая причина - набор символов. Этот ответ показывает пару обходных путей. Индексный предел, как вы сделали это тоже работает.

Это был очень долгий срок (MySQL-4.0) с 255 года, какой предел varchar - скорее произвольный выбор, а выбор ограничения на основе ваших данных - лучший подход.

В дополнение к тому, что размеры индексов больше для больших длин, объединения, включающие их, иногда используют механизм хранения MEMORY, что приводит к преобразованию varchar (X) в char (X), который может использовать намного больше памяти.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню