Я столкнулся со следующим, и я не уверен, что лучше всего.
Рассмотрим следующую таблицу (которая станет больше):
id PK | giver_id FK | recipient_id FK | Дата
Я использую InnoDB и, насколько я понимаю, он автоматически создает индексы для двух столбцов внешнего ключа. Однако я также буду выполнять множество запросов, в которых мне нужно сопоставить определенную комбинацию:
SELECT...WHERE giver_id = x AND recipient_id = t
.
Каждая такая комбинация будет уникальной в таблице.
Есть ли какая-то выгода от добавления индекса из двух столбцов к этим столбцам, или два отдельных индекса теоретически будут достаточными / одинаковыми?
Ответы:
Если у вас есть два одностолбцовых индекса, в вашем примере будет использоваться только один из них.
Если у вас есть индекс с двумя столбцами, запрос может быть быстрее (вы должны измерить). Индекс из двух столбцов также может использоваться как индекс из одного столбца, но только для столбца, указанного первым.
Иногда может быть полезно иметь индекс для (A, B) и другой индекс для (B). Это делает запросы, использующие один или оба столбца быстрыми, но, конечно, также использует больше дискового пространства.
При выборе индексов также необходимо учитывать влияние на вставку, удаление и обновление. Больше индексов = более медленные обновления.
источник
Индекс покрытия, например:
... будет означать, что индекс можно использовать, если упоминается запрос
giver_id
или комбинацияgiver_id
иrecipient_id
. Имейте в виду, что критерий индекса основан на крайнем левом положении - запрос, относящийся только кrecipient_id
, не сможет использовать индекс покрытия в предоставленном мною утверждении.Кроме того, MySQL может использовать только один индекс для каждого SELECT, поэтому покрывающий индекс будет лучшим средством оптимизации ваших запросов.
источник
MySQL can only use one index per SELECT
это больше не правда, было бы неплохо, если бы вы отредактировали свой ответ, чтобы он был обновлен.recipient_id
?INDEX (col1, col2, col3, col4)
то индекс будет применяться для поиска с такимWHERE
предложением, какcol1 = 'A'
илиcol1 = 'A' AND col2 = 'B'
илиcol1 = 'A' AND col2 ='B' AND col3 = 'C' AND col4 = 'D'
, но этот конкретный индекс не будет использоваться ни для чего подобногоWHERE col2 = 'B'
илиWHERE col3 = 'C' AND col4 = 'D'
потому что поля поиска не оставлены большей частью в определении индекса. Вам придется добавить дополнительные индексы для покрытия этих полей.Если один из индексов внешнего ключа уже является очень избирательным, то ядро базы данных должно использовать его для указанного вами запроса. Большинство механизмов баз данных используют какую-то эвристику, чтобы выбрать оптимальный индекс в этой ситуации. Если ни один из индексов сам по себе не является очень селективным, вероятно, имеет смысл добавить индекс, построенный на обоих ключах, поскольку вы говорите, что будете часто использовать этот тип запроса.
Еще одна вещь , чтобы рассмотреть, если вы можете устранить поле PK в этой таблице и определить первичный индекс ключа на
giver_id
иrecipient_id
полей. Вы сказали, что комбинация уникальна и, возможно, она сработает (учитывая множество других условий, на которые можете ответить только вы). Однако обычно я думаю, что добавленная сложность не стоит хлопот.источник
Также следует учитывать, что характеристики производительности обоих подходов будут основаны на размере и мощности набора данных. Вы можете обнаружить, что двухколоночный индекс становится более эффективным только при определенном пороговом уровне размера набора данных или наоборот. Ничто не может заменить метрики производительности для вашего конкретного сценария.
источник