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子句中可以有一个冗长的条件吗?整个数据将从一张表中扫描。
答案 0 :(得分:3)
为什么不使用这个更简单的?而不是使用一堆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
答案 1 :(得分:1)
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
并获得执行计划。然后查找表扫描和索引扫描,并考虑更改索引以避免它们。有时,如果查询中返回的行数很高,则全表扫描是正确的方法。
答案 2 :(得分:1)
使用索引优化此查询很困难。但是,我认为您可以将其拆分为两部分以获得正确的索引使用:
(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足够聪明,可以在原始数据上使用它,但这也值得一试。
答案 3 :(得分:0)
我会尝试为您的查询(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 )