Проблема с ИЛИ в составном индексе - PullRequest
1 голос
/ 25 июня 2011

Во многих моих запросах у меня есть сценарий, подобный

SELECT * from myTable m 
where m.userId = :userId
AND  (m.to = :contactNumber OR m.from = :contactNumber)
AND .....

Так что я создал составной индекс для (userId, to, from)

Он отлично работает, если OR заменяется на AND, но в случае OR он просто использует индекс для userId.

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

Ответы [ 2 ]

2 голосов
/ 25 июня 2011

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

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

Один из способов сделать это - добавить дополнительный индекс в userId:from и затем используйте два отдельных запроса в объединении, оба из которых могут использовать свой собственный индекс для эффективного поиска строк.Что-то вроде:

select * from myTable m
    where m.userId = :userId and m.to = :contactNumber
union
select * from myTable m
    where m.userId = :userId and m.from = :contactNumber

Первый запрос, который, скорее всего, будет использовать ваш исходный индекс, поскольку userId:to - это два его компонента верхнего уровня.Вы могли бы также иметь индекс только для этого, но, вероятно, в этом нет необходимости, поскольку у вас уже есть пригодный для использования индекс (и он может использоваться для других ваших запросов, где вы хотите строки со всеми тремя компонентами).

Второй запрос, вероятно, будет использовать новый индекс для эффективного поиска его строк.

union объединит два запроса и удалит дубликаты.Это необходимо для соответствия цели исходного запроса.Если вы знали, что между запросами не может быть пересечения, вы можете использовать union all, чтобы пропустить (ненужный) шаг удаления дубликатов, но я не думаю, что вы можете сделать это здесь.

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

Теперь имейте в виду, что это general совет.Я сам человек DB2, поэтому то, что я здесь выдвинул, основано на общих знаниях о том, как базы данных работают внутри, а не на особенностях MySQL.

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

2 голосов
/ 25 июня 2011

Составной индекс ищет несколько вещей, объединенных вместе. Это может помочь рассмотреть его как индекс различных объединенных столбцов.

Так что, если вы используете или, вы ищете комбинацию идентификатора пользователя и с, ИЛИ пользователя и с. Но не все 3 вместе!

Это немного зависит от содержимого и всего, но вы могли бы добавить 2 компонента для обоих «под» запросов (например, userid и to + userid и from). Но разве недостаточно идентификатор пользователя? Если это сведет ваши строки достаточно, чтобы они были управляемыми, я бы не стал добавлять все виды составных индексов ...

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