2010-01-28 3 views
30

Мне немного стыдно спрашивать об этом, так как я много лет работаю с MySQL, но хорошо.Несколько и одиночные индексы

У меня есть таблица с двумя полями, a и b. Я буду работать следующие запросы на него:

  • SELECT * FROM ... WHERE A = 1;
  • SELECT * FROM ... WHERE B = 1;
  • SELECT * FROM ... WHERE A = 1 AND B = 1;

С точки зрения производительности, по меньшей мере, один из следующих конфигураций индексов медленнее по крайней мере для одного запроса? Если да, пожалуйста, уточните.

  1. ALTER TABLE ... ADD INDEX (a); ALTER TABLE ... ADD INDEX (b);
  2. ALTER TABLE ... ADD INDEX (a, b);
  3. ALTER TABLE ... ADD INDEX (a); ALTER TABLE ... ADD INDEX (b); ALTER TABLE ... ADD INDEX (a, b);

Спасибо (обратите внимание, что речь идет о не являющихся уникальных индексах)

ответ

27

Да, по крайней мере один случай, значительно медленнее. Если вы только определить следующий индекс:

ALTER TABLE ... ADD INDEX (a, b); 

... то запрос SELECT * FROM ... WHERE B = 1; не будет использовать этот индекс.

Когда вы создаете индекс с составным ключом, порядок столбцов ключа важен. Рекомендуется попытаться упорядочить столбцы в ключе, чтобы повысить избирательность, причем наиболее избирательные столбцы находятся в самой левой части ключа. Если вы этого не сделаете и поставьте неселективный столбец в качестве первой части ключа, вы рискуете вообще не использовать этот индекс. (Источник: Tips on Optimizing SQL Server Composite Index)

+6

И есть ли какое-либо преимущество в конфигурации №3 вместо # 1? –

+6

Да, может быть преимущество. Составной индекс может стать индексом покрытия, когда все данные в запросе хранятся внутри самого индекса. В общем случае 'SELECT A, B FROM ... WHERE A = 1;' будет быстрее, если он использует составной индекс в '(A, B)', поскольку запрос не нужно будет извлекать любые данные из таблицы , Данные уже находятся в индексе. –

+1

Помните, что индексы занимают пространство и могут скомпрометировать небольшую производительность при вставках и обновлениях. Я бы пошел с вариантом 3, только если ваше приложение будет делать запросы, которые оправдывают дополнительный индекс ... Советы по индексу покрытия: http://www.sql-server-performance.com/tips/covering_indexes_p1.aspx –

22

Очень маловероятно, что простое существование индекса замедляет запрос SELECT: он просто не будет использоваться.

Теоретически оптимизатор может неправильно выбрать более длинный индекс на (a, b), а не один на (a), чтобы обслуживать запрос, который ищет только a.

На практике я никогда не видел его: MySQL обычно делает противоположную ошибку, принимая более короткий индекс, когда существует более длинный.

Update:

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

(a, b); (b) 

или

(b, a); (a) 

MySQL можно также использовать два отдельных индексов с index_intersect, поэтому создание этих индексов

(a); (b) 

также ускорит запрос a = 1 AND b = 1, хотя в меньшей степени, чем любое из вышеперечисленных решений.

Вы также можете прочитать эту статью в своем блоге:

Обновление 2:

Кажется, что я, наконец, понял ваш вопрос :)

ALTER TABLE ... ADD INDEX (a); ALTER TABLE ... ADD INDEX (b); 

Отлично подходит для a = 1 и b = 1, достаточно хорошо для a = 1 AND b = 1

ALTER TABLE ... ADD INDEX (a, b); 

Отлично для a = 1 AND b = 1, почти отлично подходит для a = 1, плохое для b = 1

ALTER TABLE ... ADD INDEX (a); ALTER TABLE ... ADD INDEX (b); ALTER TABLE ... ADD INDEX (a, b); 

Отлично для всех трех запросов.

+0

Ну, да, но зачем добавлять ненужные индексы? –

+1

Я думаю, что вы неправильно интерпретируете OP. Я думал, что он спрашивает: «Один из них медленнее, чем другие?» а не «Является ли это одним из таких медленнее, чем отсутствие индексов?» –

4

SQL будет выбирать индекс, который наилучшим образом покрывает запрос. Индекс по A, B будет охватывать запрос как для случая 1 и 3, но не на 2 (так как основной столбец индекса A)

Таким образом, чтобы охватить все три запроса нужны два индекса:

ALTER TABLE ... ADD INDEX (a, b); ALTER TABLE ... ADD INDEX (b) 
0

Для примера у вас есть индексный набор №3. Mysql выберет одиночные индексы A и B для одного столбца, где предложения, и используйте индекс соединений для предложения A B где.

Смежные вопросы