1) Приведенный ниже запрос выполняется минимум для 1 миллиона записей. Прямо сейчас это дает результаты в 70ms to 1s
. Хорошая производительность. Какое идеальное время, когда запрос должен возвращать результаты. (Система MySql InnoDB) все столбцы находятся в одной таблице
SELECT
*
FROM
rgb
WHERE
((tcount = 16 AND r1 = 3 AND r2 = 5
AND r3 = 8)
OR (r1 = 8 AND r2 = 5)
OR (r1 = 5 AND r2 = 8)
OR (r1 = 3 AND r2 = 8)
OR (r1 = 5 AND r2 = 3)
OR (r1 = 3 AND r2 = 5)
OR (r1 = 8 AND r2 = 3))
order by case
when
(tcount = 16 AND r1 = 3 AND r2 = 5
AND r3 = 8)
then
1
else 2
end
2) Могу ли я включить в предложение WHERE длинное условие? Все данные должны быть отсканированы из одной таблицы.
4 ответа
Я бы попытался иметь индекс покрытия для вашего запроса (r1, r2, r3, tcount)
И предложение WHERE вроде
where
r1 in ( 3, 5, 8 )
AND r2 in ( 3, 5, 8 )
AND r1 != r2
OR ( r1 = 3 and r2 = 5 and r3 = 8 and tcount = 16 )
Почему бы не использовать этот попроще? вместо использования набора OR
s
SELECT
*
FROM
rgb
WHERE
((tcount = 16 AND r1 = 3 AND r2 = 5
AND r3 = 8)
OR (r1, r2) IN ((8,5),(5, 8), (3, 8),(5,3),(3,5),(8,3))
order by case
when
(tcount = 16 AND r1 = 3 AND r2 = 5
AND r3 = 8)
then
1
else 2
end
(r1, r2) IN ( ...)
- я не знал, что это возможно :)
Оптимизация SQL частично зависит от распределения ваших данных. Мы не можем его угадать, поэтому мы не можем ответить, каково стандартное время для вашего запроса. Но MySQL может сделать это за вас. Используйте EXPLAIN:
EXPLAIN SELECT
*
FROM
rgb
WHERE
((tcount = 16 AND r1 = 3 AND r2 = 5
AND r3 = 8)
OR (r1 = 8 AND r2 = 5)
OR (r1 = 5 AND r2 = 8)
OR (r1 = 3 AND r2 = 8)
OR (r1 = 5 AND r2 = 3)
OR (r1 = 3 AND r2 = 5)
OR (r1 = 8 AND r2 = 3))
order by case
when
(tcount = 16 AND r1 = 3 AND r2 = 5
AND r3 = 8)
then
1
else 2
end
И получите план выполнения. Затем поищите сканирование таблиц и сканирование индексов и подумайте об изменении индексов, чтобы избежать их. Иногда, если количество строк, возвращаемых в запросе, велико, правильным подходом является полное сканирование таблицы.
Этот запрос сложно оптимизировать с помощью индексов. Но я думаю, что вы можете разделить его на две части, чтобы правильно использовать индекс:
(SELECT r.*
FROM rgb r
WHERE (tcount = 16 AND r1 = 3 AND r2 = 5 AND r3 = 8)
) UNION ALL
(SELECT r.*
FROM rgb r
WHERE (r1 = 8 AND r2 = 5) OR
(r1 = 5 AND r2 = 8) OR
(r1 = 3 AND r2 = 8) OR
(r1 = 5 AND r2 = 3) OR
(r1 = 3 AND r2 = 5) OR
(r1 = 8 AND r2 = 3)
)
order by (case when (tcount = 16 AND r1 = 3 AND r2 = 5 AND r3 = 8)
then 1
else 2
end);
Затем создайте индекс на:
create index rgp_r1_r1_r3_tcount on rgp(r1, r2, r3, tcount);
Этот индекс должен работать с обоими подзапросами. Я не думаю, что MySQL достаточно умен, чтобы использовать его с исходными данными, но это тоже стоит попробовать.
Похожие вопросы
Новые вопросы
mysql
MySQL — это бесплатная система управления реляционными базами данных (RDBMS) с открытым исходным кодом, которая использует язык структурированных запросов (SQL). НЕ ИСПОЛЬЗУЙТЕ этот тег для других БД, таких как SQL Server, SQLite и т. д. Это разные БД, которые используют свои собственные диалекты SQL для управления данными. В вопросе всегда указывайте точную версию сервера. Версии 5.x сильно отличаются по своим возможностям от версий 8+.