SQL查询优化为100万条记录

时间:2014-02-24 11:34:11

标签: mysql sql

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 个答案:

答案 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 )