Mysql 子查询执行时间:localhost=2秒/server=98+;秒
我可以在子查询方面寻求帮助吗 当我在本地XAMP mySQL数据库上运行查询时,查询需要2秒钟才能完成。然而,在我的Web服务器上使用相同的数据库时,相同的查询需要98秒以上的时间才能返回相同的结果 当我说相同时,记录是从HeidiSQL导出和插入的,因此我确信数据集是正确的。数据库DDL也是从HeidiSQL创建的,但我猜我可能错过了创建数据库精确副本的一些关键步骤 我还使用Heidi的导出功能创建了一个。尽管我应该指出,在小提琴上执行查询比在现实生活中要快得多 我正在执行的查询是Mysql 子查询执行时间:localhost=2秒/server=98+;秒,mysql,subquery,Mysql,Subquery,我可以在子查询方面寻求帮助吗 当我在本地XAMP mySQL数据库上运行查询时,查询需要2秒钟才能完成。然而,在我的Web服务器上使用相同的数据库时,相同的查询需要98秒以上的时间才能返回相同的结果 当我说相同时,记录是从HeidiSQL导出和插入的,因此我确信数据集是正确的。数据库DDL也是从HeidiSQL创建的,但我猜我可能错过了创建数据库精确副本的一些关键步骤 我还使用Heidi的导出功能创建了一个。尽管我应该指出,在小提琴上执行查询比在现实生活中要快得多 我正在执行的查询是 SELEC
SELECT d.dayID, d.dayDate, d.item, w.Idx, w.word, w.wordID, w.asize, w.span
FROM words w
INNER JOIN days d ON w.dayID = d.dayID
WHERE w.word IN (
SELECT w1.word
FROM words w1
INNER JOIN days d1 ON w1.dayID = d1.dayID
WHERE d1.dayDate = '2012-02-27'
AND d1.Item = 'a'
AND w1.span = 24
AND w1.asize = 6
)
AND w.span = 24
AND w.asize = 6
GROUP BY d.dayDate, d.item
Order by d.dayDate, w.asize DESC, w.Idx;
它的目的是从Days表返回日期和项目的列表,其中word表中有重复的单词
上面的查询将返回与此类似的结果
dayID dayDate item Idx word wordID asize span
1974 2012-11-22 B 3 item b 1367339 6 24
4370 2015-03-10 B 1 item b 3024989 6 24
使用phpMyAdmin,我在word字段中添加了一个索引,这使时间从98秒减少到46秒。但是,46秒当然也太长了
另外需要注意的是,单词表实际上包含大约300万条记录。其他查询(非子查询)在眨眼之间运行。我想我只是不擅长子查询
我想问一下,有没有人能为我指出正确的方向,以确定为什么在服务器上执行查询会花费如此长的时间?一般来说,在处理复杂或大的子查询时,应该避免在中使用
。这是因为
中的条件必须为数据源中的每一行计算一次。因此,如果您的数据源有1000行,并且
条件中的有1000个元素,则执行如下:
- 对于第1行,运行子查询并检查该值是否在子查询结果中
- 对于第2行,运行子查询并检查该值是否在子查询结果中
- 等等
(不用说,如果子查询很复杂,这将是一个巨大的性能损失)
所以,你可以做一些事情来加快速度:
不要在
中使用,而是使用加入
不要使用子查询,而是创建一个临时表,添加适当的索引,然后使用JOIN
我将处理选项2。如果需要,可以用完整的子查询替换临时表
那么,让我们创建一个临时表:
drop table if exists temp_words;
create temporary table temp_words
SELECT w1.word
FROM words w1
INNER JOIN days d1 ON w1.dayID = d1.dayID
WHERE d1.dayDate = '2012-02-27'
AND d1.Item = 'a'
AND w1.span = 24
AND w1.asize = 6;
alter table temp_words
add index w(word);
现在,不要在
中使用,而是使用加入
:
SELECT d.dayID, d.dayDate, d.item, w.Idx, w.word, w.wordID, w.asize, w.span
FROM words w
INNER JOIN days d
ON w.dayID = d.dayID
INNER JOIN temp_words as w1 -- Replace 'temp_words' with your subquery
-- if you don't want to use a temp table
ON w.word = w1.word
WHERE w.span = 24
AND w.asize = 6
GROUP BY d.dayDate, d.item
Order by d.dayDate, w.asize DESC, w.Idx;
我想您会注意到,通过使用JOIN
而不是中的,可以大大提高性能
关于临时表,您必须了解的事项:
它们的行为类似于普通表,因此您可以像使用任何其他表一样使用它们:您可以插入、更新和删除行,您可以添加索引或以任何方式更改它们,如果它们不再有用,您可以删除它们
它们仅对创建它们的连接可见。这意味着两个连接可以创建具有相同名称(但可能具有不同结构)的临时表,并且每个连接可以使用自己的“副本”
一旦连接关闭或终止,它们将被删除,因此如果关闭或终止连接,则必须再次创建它们
哇,多好的回答啊。有很多东西需要学习和吸收。关于删除子查询。。。我很乐意。我只是觉得它们非常混乱和复杂。非常感谢。我会尝试你的建议和更新留下评论+我现在很高兴,这只是SQL巫术。我为我的测试选择了更简单的选项。。。这就是“用子查询替换临时单词”,因为这是一个快速测试。从98秒(我的最佳时间)到0.125秒(WTF)与您的加入。我需要用你提到的其他信息进行更多的测试。我特别想看看这些“临时表”。。。我觉得他们会很有帮助。我以前听说过它们,但从来没有觉得我有理由使用它们,所以我就忽略了它们。不管怎样,我接受了你的回答,并把你推到了我的“给这些人买杯啤酒”名单的首位。我认为,当有人提供帮助时,查看他们的个人资料是一种礼貌。通常也有“额外”的宝石需要学习。我遵循了您提供的链接,在同意内容的同时,我必须承认我也犯了没有首先应用“您尝试了什么”原则的错误。有时候,真的不知道从哪里开始,但有时候是懒惰。它只是强调了努力的重要性——即使它走错了方向。@Johnny很乐意帮忙!临时表是将大任务分解为小步骤的强大工具:它们可以用于许多“分而治之”的解决方案。至于你的其他评论,我只能说:既然你知道这种方法,那么就使用它并向前支付;这样每个人都赢了!(是的,喝杯啤酒就好了!)再次谢谢你,巴兰卡。我从你身上学到了很多东西。我也会尽力提前付款。干杯。今天我将尝试一些测试,并根据Barranka的建议更新Q。