简体   繁体   English

如何优化以下mysql查询

[英]how to optimize the following mysql query

I have a trouble in the mysql query . 我在mysql查询中遇到麻烦。 the query is following. 查询如下。

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);

how can I optimize the query to which maybe can drop the OR word . 我如何优化可能将OR字删除的查询。 thanks. 谢谢。

also, the query may be extended like follow . 同样,查询可以像follow一样扩展。

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     ... ;

can someone explain about the Train of thought of The solution, thanks very much. 有人可以解释一下解决方案的思路吗,非常感谢。

The query looks fine as is. 该查询看起来很好。 Sometimes it is the case that you want one or another condition met. 有时是您希望满足一个另一个条件的情况。 It is the optimizer's job to find the best way to execute the query. 找到执行查询的最佳方法是优化器的工作。

You can try help the optimizer, but that shouldn't actually be necessary, so do this only if you really have performance issues. 可以尝试帮助优化器,但这实际上不是必需的,因此只有在确实存在性能问题时才这样做。

Your query could be written as 您的查询可以写成

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);

because of overlapping criteria, but I doubt that would help the optimizer much. 因为重叠的条件,但是我怀疑这对优化程序有很大帮助。

You could also do: 您也可以这样做:

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)
);

So you'd list all values in question first (there is no condition that requires a level not in 3-7, and there is no condition requiring last_time outside 0-6). 因此,您将首先列出所有有问题的值(没有条件需要一个不在3-7中的level ,并且没有条件要求last_time在0-6之外)。 Only then list the single conditions. 仅然后列出单个条件。 This may or may not help the optimizer. 这可能会也可能不会帮助优化器。

In any way you should have a composite index on level + last_time . 无论如何,您都应在level + last_time上拥有一个复合索引。 Whether using this index or doing a full table scan is faster depends on the data, but you should offer such index anyway. 使用此索引还是执行全表扫描更快取决于数据,但是无论如何您都应提供这样的索引。

Often the quickest solution is the split it to multiple UNIONed queries. 通常最快的解决方案是将其拆分为多个UNIONed查询。 Then each smaller query can use indexes efficiently. 然后,每个较小的查询都可以有效地使用索引。

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);

Let's check if MySQL is smart enough to optimize the OR: 让我们检查一下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" is a table which contains 1M ints. “ seq”是一个包含1M个整数的表。

Well, MySQL optimizes the OR just fine. 好吧,MySQL可以优化OR。 It uses the index just as you'd expect. 它按照您的期望使用索引。 There is no need to tweak the query further. 无需进一步调整查询。

I suggest you check EXPLAIN of your query to verify your MySQL optimizes it properly. 我建议您检查查询的EXPLAIN以验证您的MySQL是否正确地对其进行了优化。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM