Как вы можете сделать эквивалент MINUS в MySQL, все еще используя индекс? - PullRequest
1 голос
/ 26 мая 2011

Я долго искал, как сделать запрос, подобный этому, но использую индекс.

SELECT * FROM aliens_tmp 
WHERE creator !=  'a'
AND COUNTRY = 'UK' 
ORDER BY id DESC LIMIT 0, 10

Какой бы индекс я ни создал, он не получит хит из-за столкновения! = С включеннымприрода индексов.

Так что я подумал о том, чтобы сделать минус, где я делаю что-то вроде

SELECT * FROM aliens_tmp 
WHERE COUNTRY = 'UK 
MINUS
SELECT * FROM aliens_tmp 
WHERE CREATOR = 'a' 
ORDER BY id DESC LIMIT 0, 10

... но МИНУС не существует.Поэтому я посмотрел и решил, что могу использовать старый трюк, упомянутый в http://www.bitbybit.dk/carsten/blog/?p=71, который кратко равен

SELECT DISTINCT a.member_id, a.name
FROM a LEFT JOIN b USING (member_id, name)
WHERE b.member_id IS NULL

, но это не помогает мне с первоначальной целью сделать МИНУС при сохранении использованияиндекса, так как любое соединение с моей собственной таблицей все еще должно исключить моего создателя, что вызывает промах из-за исключить Любые идеи?

Ответы [ 3 ]

0 голосов
/ 26 мая 2011

Индекс на создателя, вероятно, не будет очень полезным, даже если он может быть использован. ! = a, вероятно, вернет более половины строк в таблице. В этом случае сканирование таблицы будет более эффективным, чем использование индекса. Индекс по стране МОЖЕТ помочь, если предположить, что есть много стран, но если половина ваших пользователей находится в Великобритании, у вас тоже будет такая же проблема.

Вы можете рассмотреть возможность разделения ваших данных на две таблицы: «создатели», а не «создатели», если это имеет смысл для вашего приложения.

0 голосов
/ 26 мая 2011

Если большая часть вашей таблицы состоит из строк с creator != 'a', то использование индекса не даст вам никакого преимущества. Однако если у вас есть в основном строки с creator='a', то вы можете рассмотреть возможность присвоения таких значений создателю (или использования enum), что если вы упорядочите по создателю, 'a' будет идти первым. Вместо проверки на creator != 'a' вы можете использовать условие creator > 'a', которое идеально подходит для использования индексов btree.

ОБНОВЛЕНИЕ после получения дополнительной информации о создателе:

Таким образом, ваше условие creator != 'a' имеет крайне низкую селективность, и попытка использовать индекс для создателя бессмысленна. Вы ограничиваете свои результаты и упорядочиваете их по id desc, поэтому ключ по стране следует использовать для возврата как можно меньшего числа строк, просто проверяя каждую строку, начиная с наибольшего идентификатора, на то, удовлетворяет ли она условиям, пока не будет достаточно для вашего лимита. Если в вашем explain select ... вы увидите ключ: страна и количество строк, близких к 10, он не будет работать быстрее.

0 голосов
/ 26 мая 2011

В этом случае индекс ничего не купит, ваш самый быстрый запрос с != будет вашим самым быстрым вариантом.

Причина в том, что для выполнения МИНУС, о котором вы говорите, базе данных потребуется извлечь все строки, а затем проверить каждую строку по индексу, чтобы определить, следует ли его удалить. Для этого необходимо проверить каждую строку в таблице.

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

Это означает, что ваш исходный запрос будет быстрее, даже если бы была операция MINUS, как вы описали.

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

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