Я действительно смущен этими двумя запросами, они имеют нестабильную скорость запроса. Вот моя схема с двумя таблицами;

Таблица сообщений: (идентификатор, заголовок, дата и т. Д.) [Индекс даты]

Таблица отношений: (news_id, Relationship_id) [индексы есть для обеих строк и каждой строки]

Запрос A:

SELECT *
FROM posts
WHERE id IN (
    SELECT news_id
    FROM relationships
    WHERE relation_id IN (?)
)
AND status = 1
ORDER BY `date` DESC

Запрос Б:

SELECT *
FROM posts AS p
INNER JOIN relationships AS r ON r.news_id = n.id
WHERE r.relation_id IN (?)
AND n.status = 1
ORDER BY n.date DESC

Теперь странная часть - это результаты тестов; сначала пытаемся использовать Relationship_id из 30 строк;

Запрос A: всего 30, запрос занял 5,56 секунды.

Запрос B: всего 30, запрос занял 0,03 секунды

A медленнее на меньшем количестве строк, B - скорость на меньшем количестве строк. Затем пытаемся использовать Relationship_id, имеющую 3k строк;

Запрос A: всего 3850, запрос занял 0,05 секунды.

Запрос B: всего 3850, запрос занял 0,70 секунды.

Так что меня это смутило, с большим количеством данных теперь A работает быстрее. И, наконец, попытка multi Relations_id с + 10k строками; пример; relation_id IN (1, 2, 3, 4)

Запрос A: всего 18 906, запрос занял 0,01 сек.

Запрос B: всего 18 906, запрос занял 3,34 секунды.

Так что я должен делать? Запрос A - это скорость для такого большого количества строк, но медленная с меньшим количеством строк. Есть ли еще одно верное предложение для этого запроса? (извините за плохой английский или грамматические ошибки)

ИЗМЕНИТЬ

Вот SQL EXPLAIN s;

Запрос A с 30 строками Запрос A с 30 строками

Запрос B с 30 строками query B

Запрос A с 18k строками query a

Запрос B с 18k строками query b 2

1
musa 12 Май 2013 в 19:51
Не могли бы вы объяснить пример с 30 рядами и большой пример? where in не должен занимать 5 секунд. Вы уверены, что никакие другие вопросы не мешают измерениям? Это повторяется?
 – 
flaschenpost
12 Май 2013 в 19:56
Есть ли у posts.id указатель?
 – 
Joachim Isaksson
12 Май 2013 в 19:57
Да, это основное
 – 
musa
12 Май 2013 в 19:58
Я думаю, вам нужно будет использовать EXPLAIN в запросах и выложите результат. Все остальное в значительной степени предположение.
 – 
Joachim Isaksson
12 Май 2013 в 20:01
Как это; pastebin.com/1aN4JcjC
 – 
musa
12 Май 2013 в 20:02

1 ответ

Лучший ответ

Очень странно, но это MySQL ;-)

Оптимизатор считает, что status = 1 является сильным ограничением. Если это так, вы получите

select status=1, count(*) as num from posts group by status=1

Если только небольшая часть вашей таблицы содержит status=1, тогда решение с 30 строками все еще неплохо с точки зрения mysqls.

Если большая часть имеет status = 1, вам следует попробовать запрос с

from posts ignore index (status) ...

Или

from posts force index (id) ...

Чтобы обеспечить соблюдение правила "где-в-решении".

Более подробную информацию вы можете получить через

explain select count(*) from relationships where relation_id in (1)

Это показывает, какой размер ожидает оптимизатор на основе статистики индекса.

Проблема с фиксированными индексными подсказками в том, что они исправлены. Это означает, что они подходят как для хороших, так и для плохих сценариев.

Иногда временная таблица помогает избежать этого, вы можете сохранить в ней соответствующие отношения.

0
flaschenpost 12 Май 2013 в 20:41
На самом деле, я пробовал без «где статус» и «порядок по», узкое место выглядело как порядок. Запрос B без "упорядочить по" занял 0,0082 секунды с + 10 тыс. Строк
 – 
musa
12 Май 2013 в 20:53