如何用两个where子句优化SQL查询?

时间:2011-01-22 10:02:32

标签: mysql

我的查询是这样的

SELECT * FROM tbl1
JOIN tbl2 ON something = something
WHERE 1 AND (tbl2.date = '$date' OR ('$date' BETWEEN tbl1.planA AND tbl1.planB ))

当我运行此查询时,它比例如此查询

慢得多
SELECT * FROM tbl1
JOIN tbl2 ON something = something
WHERE 1 AND ('$date' BETWEEN tbl1.planA AND tbl1.planB )

SELECT * FROM tbl1
JOIN tbl2 ON something = something
WHERE 1 AND tbl2.date = '$date'

在localhost中,第一个查询大约需要0.7秒,第二个查询大约需要0.012秒,第三个查询大约需要0.008秒。

我的问题是你如何优化这个?如果我目前在表中有1000行,显示第一个查询需要0.7秒,如果我有10.000行,则需要7秒?与第二次查询(0.12秒)和第三次查询(0.08)相比,这是一个巨大的减速。

我尝试过添加索引,但结果没有什么不同。

由于

编辑:此应用程序仅在本地运行,因此无需担心网络速度。

抱歉,我没有包含EXPLAIN,因为我的真实查询要复杂得多(约5个连接)。但是连接(我认为)并不重要,因为我已经尝试省略它们并且仍然得到与上面大致相同的结果。

日期属于tbl1,planA和planB属于tbl2。我已经尝试将索引添加到tbl1.date,tbl2.planA和tbl2.planB,但结果无关紧要。

通过架构你的意思是MyISAM还是InnoDB?这是MyISAM。

好的,我会立即发布我的查询。希望这不是那么令人困惑。

SELECT *
FROM tb_joborder jo
LEFT JOIN tb_project p ON jo.project_id = p.project_id
LEFT JOIN tb_customer c ON p.customer_id = c.customer_id
LEFT JOIN tb_dispatch d ON jo.joborder_id = d.joborder_id
LEFT JOIN tb_joborderitem ji ON jo.joborder_id = ji.joborder_id
LEFT JOIN tb_mix m ON ji.mix_id = m.mix_id
WHERE dispatch_date = '2011-01-11'
OR '2011-01-11'
BETWEEN planA
AND planB
GROUP BY jo.joborder_id
ORDER BY customer_name ASC 

描述输出

id  select_type     table   type    possible_keys   key     key_len     ref     rows    Extra
1   SIMPLE  jo  ALL     NULL    NULL    NULL    NULL    453     Using temporary; Using filesort
1   SIMPLE  p   eq_ref  PRIMARY     PRIMARY     4   db_dexada.jo.project_id     1    
1   SIMPLE  c   eq_ref  PRIMARY     PRIMARY     4   db_dexada.p.customer_id     1    
1   SIMPLE  d   ALL     NULL    NULL    NULL    NULL    2048    Using where
1   SIMPLE  ji  ALL     NULL    NULL    NULL    NULL    455      
1   SIMPLE  m   eq_ref  PRIMARY     PRIMARY     4   db_dexada.ji.mix_id     1    

3 个答案:

答案 0 :(得分:1)

您可以使用UNION合并第二和第三查询的结果。

More关于UNION。

答案 1 :(得分:1)

首先想到的是将两者联合起来:

SELECT * FROM tbl1
JOIN tbl2 ON something = something
WHERE 1 AND ('$date' BETWEEN planA AND planB )

UNION ALL

SELECT * FROM tbl1
JOIN tbl2 ON something = something
WHERE 1 AND date = '$date'

您提供的优化太少。我们对您的数据结构一无所知。

答案 2 :(得分:0)

即使大多数慢查询通常是由于查询本身或使用过的表的索引设置,您也可以尝试使用MySQL Query Profiler找出瓶颈所在。自5.0.37版以来,它已经在MySQL中实现。

在开始查询之前,请使用以下语句激活探查器:

 mysql> set profiling=1;

现在执行您的长查询。

mysql> show profiles;

您现在可以找出长查询的内部编号(查询编号)。

如果您现在执行以下查询,您将获得有关花费多长时间的详细信息:

mysql> show profile for query (insert query number here);
(example output)
+--------------------+------------+
| Status             | Duration   |
+--------------------+------------+
| (initialization)   | 0.00005000 |
| Opening tables     | 0.00006000 |
| System lock        | 0.00000500 |
| Table lock         | 0.00001200 |
| init               | 0.00002500 |
| optimizing         | 0.00001000 |
| statistics         | 0.00009200 |
| preparing          | 0.00003700 |
| executing          | 0.00000400 |
| Sending data       | 0.00066600 |
| end                | 0.00000700 |
| query end          | 0.00000400 |
| freeing items      | 0.00001800 |
| closing tables     | 0.00000400 |
| logging slow query | 0.00000500 |
+--------------------+------------+

这是一种更通用的管理方法,但可以帮助缩小甚至找出导致查询速度慢的原因。

可以在MySQL文章中找到关于如何使用MySQL Query Profiler的好教程{。{3}}。