MySQL - какой ключ более оптимизирован - PullRequest
3 голосов
/ 29 июня 2009

Допустим, у меня есть большая база данных, которая состоит из продуктов в группах. Допустим, есть 5 групп, в каждой из которых по 100 000 товаров. идентификаторы продуктов являются случайными целыми числами (как и идентификаторы групп)

Мне нужно найти товар в определенной группе. У меня вопрос, какой первичный ключ более эффективен:

  1. (sid, pid)
  2. (pid, sid)

sid, pid интуитивно понятен, но при поиске в таком порядке MySQL должен будет изолировать 100 000 из 500 000 строк, а затем найти одно число из 100 000. С другой стороны, (pid, sid) звучит для меня более оптимально, так как это заставит mysql не создавать большую группу из 100 000 на первом этапе, а перейти непосредственно к нужному элементу (или до 5 элементов, если в разные случаи).

# 2 действительно быстрее?

UPDATE: ХОРОШО. Я скопировал реальную таблицу в две копии. table0 имеет первичный ключ sid, pid. У table1 есть pid, sid.

результат запроса:

объяснение выбора * из items0, где sid = 22746 и pid = 2109418034 1, «ПРОСТО», «items0», «ref», «PRIMARY», «PRIMARY», «8», «const, const», 14, «

»

объяснение выбора * из items1, где sid = 22746 и pid = 2109418034

1, 'SIMPLE', 'items1', 'ref', 'PRIMARY', 'PRIMARY', '8', 'const, const', 11, ''

Еще одно обновление: Я также добавил два ключа в одну и ту же таблицу и запустил объяснение. получил это: (Первичное начинается с sid_pid1, Index2 начинается с pid1, sid)

1, 'SIMPLE', 'items', 'ref', 'PRIMARY, index_2', 'index_2', '8', 'const, const', 13, ''

Я не уверен, какие выводы я могу сделать из этого теста?

Ответы [ 4 ]

8 голосов
/ 29 июня 2009

Не угадай, тест.

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

4 голосов
/ 29 июня 2009

Производительность запроса к СУБД SQL в значительной степени зависит от большого числа факторов - насколько фрагментирована таблица (или индекс), свежести и объема данных / статистики индекса, размера ваших кешей данных / того, сколько ЦП / память, сколько строк в таблице, конструкция запроса и т. д. и т. д. и т. д.

Хотя профилирование запросов является необходимой частью настройки производительности, одного этого недостаточно - оно должно быть частью более широкой стратегии оптимизации запросов. Сказать «протестируй и посмотри» не очень полезно (и, на мой взгляд, иногда опасно!) В общем случае из-за недетерминированной природы процесса оптимизации запросов. Один день бега это может быть просто отлично, следующий медленный (или наоборот).

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

В этом случае существует эмпирическое правило из-за природы построения B-деревьев MySQL. На странице внутренних страниц MySQL: http://forge.mysql.com/wiki/MySQL_Internals_MyISAM#The_.MYI_file вы можете видеть, что в случае неуникального индекса BTREE на двух столбцах MySQL будет хранить объединенные значения в порядке, который вы указываете. В этом конкретном примере они сохранили ASCII (или UNICODE), но в случае целочисленных значений он будет делать что-то похожее (откройте шестнадцатеричный редактор и расшифруйте действительные значения, если вы достаточно отважны!) (Также ссылка здесь http://dev.mysql.com/doc/refman/5.0/en/multiple-column-indexes.html).

Таким образом, эмпирическое правило заключается в том, чтобы сначала поместить самое селективное (ref http://www.akadia.com/services/ora_index_selectivity.html) значение, поскольку это дает обработчику запросов больше информации, чтобы сузить число строк, обработанный. Размещение менее селективного ключа FIRST заставит оптимизатор учитывать больше строк и, если это не то, что вам ТОЧНО нужно, будет неоптимальным по проекту .

Также, чтобы прокомментировать сказанное Эриком: MySQL (или другие СУБД) могут использовать любые / все ключи расширяющимся образом, чтобы помочь сузить поиск - например, если вы помещаете индекс в (A, B, C), тогда запросы, которые имеют WHERE A = .. B =, могут использовать его (в зависимости от), запросы, которые используют WHERE A =, могут использовать его, но запросы, которые запрашивают WHERE C =, не могут (обычно).

Таким образом, это также зависит от характера ваших запросов - если вы всегда запрашиваете WHERE pid = И sid =, то сначала следует выбрать самый селективный (идентификатор продукта), но если вы часто запрашиваете WHERE sid = XXXX сам, тогда sid должен идти первым (ИЛИ просто создайте другой индекс для этой ситуации, если есть различные суммы). Компромисс здесь - время / пространство - наличие дополнительного индекса удовлетворит другой класс запросов за счет дополнительного дискового пространства и увеличения операций ввода-вывода при записи.

Наконец, если вы используете INNODB, вы можете указать «кластеризованный» индекс, который на самом деле сортирует строки на диске (таблицы MyISAM в основном являются кучами). Если вы кластеризуете строки на диске с помощью sid, pid, тогда он фактически сгруппирует их вместе, чтобы вы могли извлекать целые БЛОКИ (или страницы) продуктов за раз, которые будут использовать значительно меньше операций ввода-вывода, чем только BTREE (ref *). 1030 *)

Итак, вы можете понять, почему полезно "проверить и увидеть", но без понимания основ индекса MySQL вы упускаете целый класс оптимизаций.

4 голосов
/ 29 июня 2009

Добавьте оба ключа как неосновные (или один как первичный, а другой как неосновной), затем запустите требуемый запрос, добавив «EXPLAIN» впереди. Это заставит MySQL показать вам, какой ключ он выбрал.

1 голос
/ 29 июня 2009

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

Если ваши запросы в основном относятся к типу «в каких группах этот продукт», то (pid, sid), вероятно, будут самыми быстрыми.

Если они относятся к типу "дай мне все продукты этой группы", то (sid, pid), вероятно, будет быстрее.

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