Индексы MySQL: как они работают? - PullRequest
3 голосов
/ 09 января 2011

Я полный новичок с индексами MySQL.У меня есть несколько таблиц MyISAM на MySQL 5.0x с наборами символов utf8 и сопоставлениями по 100 000 записей в каждой.Первичные ключи обычно целочисленные.Многие столбцы в каждой таблице могут иметь повторяющиеся значения.

Мне нужно быстро подсчитать, суммировать, усреднить или иным образом выполнить пользовательские вычисления для любого количества полей в каждой таблице или объединить их для любого количества других.

Я нашел эту страницу с обзором использования индекса MySQL: http://dev.mysql.com/doc/refman/5.0/en/mysql-indexes.html,, но я все еще не уверен, что правильно использую индексы.Когда я думаю, что я сделал идеальный индекс из набора полей, по которым я хочу вычислить, я получаю ошибку «индекс должен быть меньше 1000 байт».

Может кто-нибудь объяснить, как наиболее эффективно создатьи использовать индексы для ускорения запросов?

Предостережение: обновление Mysql в этом случае невозможно.Использование Navicat Light для администрирования БД, но это приложение не требуется.

Ответы [ 4 ]

8 голосов
/ 09 января 2011

Когда вы создаете индекс для столбца или столбцов в таблице 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, например:

ALTER TABLE mytable ADD KEY (column_a, column_b);

База данных собирается создать вышеупомянутое B-дерево, в котором будет четыре ключа, по одному для каждой строки:

hello-2
hello-3
how-4
foo-5

Когда вы выполняете поиск по столбцу column_a или по столбцам column_a AND column_b, база данных сможет использовать этот индекс для сужения набора записей, который необходимо проверить. Допустим, у вас есть запрос вроде:

SELECT ... FROM mytable WHERE column_a = 'hello';

Несмотря на то, что в приведенном выше запросе не указано значение для столбца column_b, он все равно может воспользоваться нашим индексом, ища все ключи, которые начинаются с «hello». По той же причине, если у вас был запрос вроде:

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. Предположим, что он работает; вы будете создавать следующие ключи:

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 в объявлении выше. Однако, вообще говоря, если вы используете длинные ключи, возможно, что-то не так с вашим дизайном стола.

Помните, что индексы с одним столбцом часто предоставляют больше полезности, чем индексы с несколькими столбцами. Вы хотите использовать многостолбцовый индекс, когда будете часто / всегда использовать его, указав все необходимые критерии в своих запросах. Кроме того, как уже упоминали другие, НЕ индексируйте каждый столбец таблицы, поскольку каждый индекс добавляет дополнительные ресурсы хранения в вашу базу данных. Вы хотите ограничить свои индексы столбцами, которые часто используются запросами, и если вам кажется, что вам нужно слишком много, вам, вероятно, следует подумать о разбиении ваших таблиц на более логичные компоненты.

1 голос
/ 09 января 2011

Похоже, вы пытаетесь поместить слишком много полей в свой индекс. Предел - это, вероятно, число байтов, необходимое для кодирования всех полей.

Индекс используется при поиске записей, поэтому вы хотите выбрать поля, в которых вы "ГДЕ" находитесь. Выбирая между этими полями, вы хотите выбрать те, которые сузят результаты быстрее всего.

Например, фильтр для мужчины / женщины обычно мало помогает, потому что вы собираетесь сэкономить только около 50% времени. Тем не менее, фильтр State может быть полезен, потому что вы разбитесь на множество других категорий. Однако, если почти все в базе данных находятся в одном состоянии, это не сработает.

1 голос
/ 09 января 2011

Помните, что индексы предназначены для сортировки и поиска строк.

Полученное сообщение об ошибке звучит так, будто оно говорит о пределе префикса в 1000 байт для индексов таблицы MyISAM.С http://dev.mysql.com/doc/refman/5.0/en/create-index.html:

Показанный здесь оператор создает индекс, используя первые 10 символов столбца имени:

CREATE INDEX part_of_name ON customer (name (10));Если имена в столбце обычно отличаются первыми 10 символами, этот индекс не должен быть намного медленнее, чем индекс, созданный из всего столбца имени.Кроме того, использование префиксов столбцов для индексов может значительно уменьшить размер файла индекса, что может сэкономить много места на диске и ускорить операции INSERT.

Поддержка префиксов и длины префиксов (если они поддерживаются) являются механизмом хранения.зависимый.Например, префикс может иметь длину до 1000 байт для таблиц MyISAM и 767 байт для таблиц InnoDB.

Возможно, вы можете попробовать индекс FULLTEXT для проблемных столбцов.

1 голос
/ 09 января 2011

Индексы, как правило, плохо подходят для пользовательских вычислений, когда пользователь может создавать свои собственные запросы. Обычно вы выбираете индексы в соответствии с конкретными запросами, которые вы собираетесь выполнять, используя EXPLAIN, чтобы увидеть, используется ли индекс.

В случае, если вы абсолютно не представляете, какие запросы могут быть выполнены, обычно лучше создать один индекс на столбец, а не один индекс, охватывающий все столбцы.

Если вы хорошо представляете, какие запросы могут часто выполняться, вы можете создать дополнительный индекс для этих конкретных запросов. Вы также можете добавить индексы позже, если ваши пользователи жалуются, что некоторые типы запросов выполняются слишком медленно.

Кроме того, индексы, как правило, не так полезны для вычисления подсчетов, сумм и средних значений, поскольку эти типы вычислений требуют просмотра каждой строки.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...