[英]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.