Когда вы создаете индекс в столбце или столбцах в таблице MySQL, база данных создает структуру данных, называемую B-деревом (при условии, что вы используете параметр индекса по умолчанию), для которого ключ каждой записи является конкатенацией значений в индексированных столбцах.
Например, предположим, что у вас есть таблица, которая определяется как:
CREATE TABLE mytable (
id int unsigned auto_increment,
column_a char(32) not null default '',
column_b int unsigned not null default 0,
column_c varchar(512),
column_d varchar(512),
PRIMARY KEY (id)
) ENGINE=MyISAM;
Тогда давайте дадим ему некоторые данные:
INSERT INTO mytable VALUES (1, 'hello', 2, null, null);
INSERT INTO mytable VALUES (2, 'hello', 3, 'hi', 'there');
INSERT INTO mytable VALUES (3, 'how', 4, 'are', 'you?');
INSERT INTO mytable VALUES (4, 'foo', 5, '', 'bar');
Теперь предположим, что вы решили добавить ключ к column_a
и column_b
like:
ALTER TABLE mytable ADD KEY (column_a, column_b);
В базе данных будет создано aforementi oned B-дерево, которое будет иметь четыре клавиши в ней, один для каждой строки:
hello-2
hello-3
how-4
foo-5
При выполнении поиска, который ссылается на column_a
столбце, или ссылаются на column_a
И column_b
столбцов, база данных будет иметь чтобы использовать этот индекс для сужения набора записей, который он должен исследовать. Скажем, у вас есть вопрос, как:
SELECT ... FROM mytable WHERE column_a = 'hello';
Несмотря на приведенный выше запрос не указывает значение для column_b
колонны, он все еще может воспользоваться нашим индексом, глядя на все лады, которые начинаются с «привет». По той же причине, если у вас есть запрос типа:
SELECT ... FROM mytable WHERE column_b = '2';
Этот запрос не будет в состоянии использовать наш индекс, потому что он должен разобрать ключи индекса сам, чтобы попытаться определить второе значение матчей, какие клавиши '2', что ужасно неэффективно.
Теперь давайте обратимся к вашему первоначальному вопросу о максимальной длине. Предположим, что мы пытаемся создать индекс, охватывающий все четыре не-PK столбцов в этой таблице:
ALTER TABLE mytable ADD KEY (column_a, column_b, column_c, column_d);
Вы получите ошибку:
ERROR 1071 (42000): Specified key was too long; max key length is 1000 bytes
В этом случае наши длины колонки, 32, 10, 512 , и 512, что в ситуации с одним байтом на символ составляет 1066, что превышает предел 1000. Предположим, что он работает DID; вы будете создавать следующие ключи:
hello-2-
hello-3-hi-there
how-4-are-you?
foo-5--bar
Теперь предположим, что вы имели значения в column_c
и column_d
, которые были очень длинные - 512 символов каждая. Даже в базовом однобайтном наборе символов ваши ключи теперь будут иметь длину более 1000 байт, о чем говорит MySQL. Это становится еще хуже с многобайтовыми наборами символов, где, казалось бы, «маленькие» столбцы могут все еще нажимать клавиши над пределом.
Если вы ДОЛЖНЫ использовать большой ключ соединения, одно решение заключается в использовании таблиц InnoDB, а не таблицы в MyISAM по умолчанию, которые поддерживают большую длину ключа (3500 байт) - вы можете сделать это путем замены ENGINE=InnoDB
вместо ENGINE=MyISAM
в декларация выше. Однако, вообще говоря, если вы используете длинные ключи, возможно, что-то не так с вашим дизайном таблицы.
Помните, что индексы с одним столбцом часто обеспечивают большую полезность, чем индексы с несколькими столбцами. Вы хотите использовать многоколоночный индекс, когда часто собираетесь/всегда используете его, указав все необходимые критерии в своих запросах. Кроме того, как отмечали другие, НЕ индексируйте каждый столбец таблицы, поскольку каждый индекс добавляет накладные расходы на хранение в вашу базу данных.Вы хотите ограничить свои индексы столбцами, которые часто используются в запросах, и если вам кажется, что вам нужно слишком много, вы, вероятно, должны подумать о том, чтобы разбить ваши таблицы на более логические компоненты.
только поместить индекс в поля, которые вы хотели бы искать, в условии where, а не те, которые вы хотите суммировать или усреднить. – dqhendricks
@dqhendricks: это впечатление, которое я получаю от страницы документа MySQL, связанной выше. Но у меня часто будет более одного поля в 'WHERE', и часто более одного поля, добавленного в индекс, вызывает эту ошибку. –
Если у вас слишком много полей, вы можете неправильно структурировать свои таблицы, например, добавив кучу полей для атрибутов, вместо того, чтобы иметь отдельную таблицу атрибутов, которую вы связываете с основной таблицей, используя внешние ключи и запросы JOIN. – dqhendricks