繁体   English   中英

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

[英]How to optimize SQL query with two where clauses?

我的查询是这样的

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    

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

更多关于UNION的信息。

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

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'

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

即使大多数慢查询通常是由于查询本身或使用过的表的索引设置,您也可以尝试使用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的文章。

暂无
暂无

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

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