如何优化以下mysql查询

时间:2017-03-31 06:39:44

标签: mysql

我在mysql查询中遇到了麻烦。查询如下。

SELECT *  
FROM group 
WHERE  (level IN (3,4,5,6) AND  last_time BETWEEN  0 AND 3) 
OR     (level IN (4,5,6,7) AND  last_time BETWEEN  0 AND 6);

如何优化可能丢弃OR字的查询。谢谢。

此外,查询可以像下面一样扩展。

SELECT *  
    FROM group 
    WHERE  (level IN (3,4,5,6) AND  last_time BETWEEN  0 AND 3) 
    OR     (level IN (4,5,6,7) AND  last_time BETWEEN  0 AND 6)
    OR     ... ;
有人可以解释一下解决方案的思路,非常感谢。

3 个答案:

答案 0 :(得分:1)

查询看起来很好。有时,您需要满足一个另一个条件。找到执行查询的最佳方法是优化器的工作。

可以尝试帮助优化器,但这实际上并不是必需的,所以只有在你确实遇到性能问题时才这样做。

您的查询可以写成

SELECT *  
FROM group 
WHERE  (level = 3 AND  last_time BETWEEN  0 AND 3) 
OR     (level IN (4,5,6,7) AND  last_time BETWEEN  0 AND 6);

因为标准重叠,但我怀疑这对优化器有多大帮助。

你也可以这样做:

SELECT *  
FROM group 
WHERE Level in (3,4,5,6,7) 
AND last_time BETWEEN 0 AND 6
AND 
(
  (level IN (3,4,5,6) AND  last_time BETWEEN  0 AND 3) 
OR
  (level IN (4,5,6,7) AND  last_time BETWEEN  0 AND 6)
);

因此,您首先列出所有有问题的值(没有条件要求{3-}不在3-7中,并且没有条件要求{0}外的{0}}。然后才列出单一条件。这可能对优化器有帮助,也可能没有帮助。

无论如何,您应该在level + last_time上拥有综合索引。是否使用此索引或执行全表扫描更快取决于数据,但您仍应提供此类索引。

答案 1 :(得分:0)

通常最快的解决方案是将其拆分为多个UNIONed查询。然后每个较小的查询都可以有效地使用索引。

SELECT *  
FROM group 
WHERE  (level IN (3,4,5,6) AND  last_time BETWEEN  0 AND 3) 
UNION
SELECT *  
FROM group 
WHERE  (level IN (4,5,6,7) AND  last_time BETWEEN  0 AND 6);

答案 2 :(得分:-1)

让我们检查MySQL是否足够聪明以优化OR:

mysql> explain splain select * from seqid in (1,2,3) or id in (4,5,6);
+----+-------------+-------+------------+-------+---------------+---------+---------+------+------+----------+-----------------------+
| id | select_type | table | partitions | type  | possible_keys | key     | key_len | ref  | rows | filtered | Extra                 |
+----+-------------+-------+------------+-------+---------------+---------+---------+------+------+----------+-----------------------+
|  1 | SIMPLE      | seq   | NULL       | range | PRIMARY       | PRIMARY | 4       | NULL |    6 |   100.00 | Using index condition |
+----+-------------+-------+------------+-------+---------------+---------+---------+------+------+----------+-----------------------+

" SEQ"是一个包含1M整数的表。

好吧,MySQL优化OR就好了。它正如您所期望的那样使用索引。无需进一步调整查询。

我建议您检查查询的EXPLAIN以验证MySQL是否正确优化它。