Если есть «другие ограничения», тогда все ставки отключены.
Между тем, глядя на то, что у вас есть ...
STRAIGHT_JOIN
, USE INDEX
и т.д., являются костылей, когда (а) не имеют индекс «правильный», или (б) оптимизатор может» t выяснить, что нужно делать. То есть, ищите другие решения.
В вашем примере вам будет лучше с равными JOIN
и INDEX(tag_id, post_id)
. Это позволило бы довести до post_tag
первый, так как есть статья WHERE
, позволяющая фильтровать там. Оптимизатор, вероятно, увидит, что t.post_id
и p.id
идентичны, поэтому запустите конец (для DESC
) (25, post_id)
в индексе и сканируйте.Затем он проверяет, есть ли запись post
(это единственное видимое использование для post
- снова, если есть «другие ограничения», все ставки отключены).
Итак, вернемся к исходному вопросу. STRAIGHT_JOIN
вынужден смотреть в post
первый. Но где 25-е? По-видимому, вблизи конец от post_tag
. Следовательно, ASC
потребовалось больше времени, чтобы найти 100 (см. LIMIT
), чем если сканирование началось с другого конца!
Предполагая, что это многие-ко-многим таблицы отображения, сделайте следующее:
CREATE TABLE post_tag (
post_id ...,
tag_id ...,
PRIMARY KEY(post_id, tag_id),
INDEX (tag_id, post_id)
) ENGINE=InnoDB;
Я обсуждаю много причин, в my blog.
Если, как было предложено, вы добавляете (tag_id, post_id DESC)
, не вводите в заблуждение, думая, что DESC
означает что-либо - оно распознается, но игнорируется. Оба детали будут сохранены ASC
. Что произойдет, так это то, что Оптимизатор достаточно умен, чтобы начать в конце 25-х и отсканировать назад. Вот «доказательство»:
US
имеет INDEX(state, population)
:
mysql> FLUSH STATUS;
mysql> SELECT city, population FROM US
WHERE state = 'OH'
ORDER BY population DESC LIMIT 5;
+------------+------------+
| city | population |
+------------+------------+
| Columbus | 736836 |
| Cleveland | 449514 |
| Toledo | 306974 |
| Cincinnati | 306382 |
| Akron | 208414 |
+------------+------------+
mysql> SHOW SESSION STATUS LIKE 'Handler%';
| Handler_read_key | 1 | -- get started at end of Ohio
| Handler_read_prev | 4 | -- read (5-1) more, scanning backwards
Единственный случай, когда MySQL отсутствует лодку, игнорируя DESC
в INDEX
декларации: ORDER BY a ASC, b DESC
не может использовать INDEX(a,b)
.
Меняет 'WHERE' на' ON' и просто выполняет регулярную 'JOIN' вместо' STRAIGHT_JOIN' что-то меняет? –
Возможно, у вас есть индекс, созданный в таблице, или может быть индекс первичного ключа по умолчанию, созданный по умолчанию в столбце Идентификатор. Вы можете повторно проиндексировать его и сделать его в том порядке, в котором вы хотите. Если вы запросите порядок, отличный от порядка вашего индекса, запрос определенно будет работать медленнее. Просто попробуйте переиндексировать в том порядке, который вы хотите запросить. –
@JoachimIsaksson, меняющий, где ON, ничего не меняет. Выполнение регулярного соединения изменит план выполнения, чтобы начать с таблицы post_tag, и это не то, что я хочу. Причина в том, что моя фактическая база данных (то, что я разместил здесь, это просто урезанный пример) имеет более сложный индексный ключ, для которого требуется запустить план выполнения по столбике. И на самом деле в этом случае мне не нужно прямое соединение, так как mysql это понимает. Таким образом, просто я просто поставил прямое соединение под тем же условием, что и моя фактическая база данных. – maalls