我在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 ... ;
有人可以解释一下解决方案的思路,非常感谢。
答案 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是否正确优化它。