Использование комбинированных индексов в MySQL - PullRequest
1 голос
/ 07 декабря 2011

У меня есть таблица перевода (MySQL MyISAM) для слов (прямо сейчас пустая, но после вставки слов она станет очень большой).

  • id_word
  • lang_original (язык от оригинального слова) VARCHAR (2)
  • lang_target (язык из переведенного слова) VARCHAR (2)
  • слово (само слово) VARCHAR (50)
  • перевод (перевод) VARCHAR (50)

Существует только 2 вида SELECT для запроса информации в этой таблице:

путем определения языка оригинала

SELECT translation FROM table WHERE lang_original='en' AND lang_target='de' AND word = 'house'
//this will return 'Haus'

, позволяя сценарию автоматически определять язык оригинала

SELECT lang_original,translation FROM table WHERE lang_target='de' AND word = 'house'
//this will return 'en','Haus'

Обычно я бы имел эти поля с отдельными индексами:

  • id_word
  • lang_original
  • lang_target
  • слово

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

  1. Должен ли я иметь только 3 индекса, как это?

    • id_word (основной / автоинкремент)
    • в сочетании: lang_target + word
    • в сочетании: lang_original + lang_target + word
  2. Должны ли эти комбинированные индексы быть UNIQUE или INDEX? Почему?

  3. Нужно ли мне также устанавливать отдельные индексы для lang_original, lang_target и word, несмотря на тот факт, что они никогда не будут фильтроваться самостоятельно?

Обновление 1 исправлено = вместо LIKE

Ответы [ 2 ]

5 голосов
/ 07 декабря 2011

Как я уже упоминал выше, использование EXPLAIN покажет вам, как выполняются запросы и какие индексы или не используются .

1) Должен ли я иметь только 3 индекса, как это?

  • id_word (основной / автоинкремент)
  • в сочетании: lang_target + word
  • в сочетании: lang_original + lang_target + word

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

(lang_target, word(10), lang_original)

Я бы предложил использовать размер нормального префикса для столбца word, чтобы они были заданной длины (скажем, 10). Подавляющее большинство слов различаются в первых 10 символах, поэтому обстоятельства, при которых он должен считываться с диска, поскольку они идентичны через 10 символов, будут редкими. Длина префикса - это баланс между размером индекса и скоростью выполнения. Больший префикс будет сталкиваться с меньшим количеством коллизий префиксов, но это будет более ресурсоемкий индекс. С другой стороны, меньший префикс сэкономит память, но может привести к большему количеству коллизий префикса (таким образом, необходимо перейти на диск, чтобы сделать окончательное определение между несколькими записями). Играйте с тем, что работает для вас. Может быть, это 5, может быть, это 15.

Должны ли эти комбинированные индексы быть UNIQUE или INDEX? Почему?

Если (lang_target, word, lang_original) будет уникальной комбинацией (что, кажется, имеет место), продолжайте и используйте ограничение UNIQUE, , но только в том случае, если вы не рубите word с префиксом * 1036. * (в этом случае может существовать несколько записей с одинаковым частичным значением word). Как индекс, я думаю, что они все еще будут функционально эквивалентны.

Нужно ли также устанавливать отдельные индексы для lang_original, lang_target и word, несмотря на тот факт, что они никогда не будут фильтроваться самостоятельно?

Столбцы в составном указателе используются слева направо. В (lang_target, word(10), lang_original) индекс можно использовать, если вы запрашиваете только условие на lang_target, но если у вас есть условие на lang_original, его нельзя использовать, если вы также не запрашиваете оба lang_target и word. Таким образом, создавайте другие индексы только для word и / или lang_original, только если вам нужно запросить без условия a lang_target. См. эту страницу документа по индексам нескольких столбцов для более подробного объяснения этого.

Еще одна мысль: Если ваши столбцы lang_ всегда будут состоять из двух символов, сделайте их CHAR вместо VARCHAR. Для столбца такого размера VARCHAR берет дополнительный байт с каждым значением для указания длины данных, тогда как это фиксированная длина с CHAR. С миллионами записей каждый байт имеет значение для размера и скорости.

1 голос
/ 07 декабря 2011

Как кто-то указал, не используйте LIKE, если вам не нужно.

Кроме того, не используйте UNIQUE, если комбинация на самом деле не уникальна, похоже, что может быть только один перевод каждого слова, поэтому UNIQUE для (lang_target, word) должен быть в порядке, но я думаю, что производительность на неуникальных индексах выше Думайте, что им не нужна уникальная проверка.

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

(lang_target, word, lang_original). Здесь важен порядок, поскольку MySQL может использовать любую левую часть индекса, поэтому оба запроса для * lang_target *, * lang_target + word * или * lang_target + word + lang_original * могут использовать этот единственный индекс.

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