这是关于SQL Server 2008 R2的问题
到目前为止,我不是DBA。我是一名java开发人员,必须不时编写SQL。 (主要嵌入代码中)。我想知道我是否在这里做错了,如果是的话,我可以做些什么来避免它再次发生。Q1:
SELECT something FROM (SELECT * FROM T1 WHERE condition1) JOIN ...
Q1有14个连接
Q2与Q1相同,但有一个例外。 (SELECT * FROM T1 WHERE condition1)之前执行,并存储在临时表中。
这不是相关的子查询。
Q2:
SELECT * INTO #tempTable FROM T1 WHERE condition1
SELECT something FROM #tempTable JOIN ...
再次,14个加入。
令我困惑的是Q1取了> 2分钟,(尝试了几次,以避免缓存发挥作用)而Q2(两个查询合并)耗时2秒!是什么给了什么?
答案 0 :(得分:48)
为什么不建议使用子查询?
数据库优化器(无论您使用的是哪种数据库)都无法始终正确地优化此类查询(使用子查询)。在这种情况下,优化器的问题是选择正确的方式来连接结果集。有几种算法可以连接两个结果集。算法的选择取决于一个和另一个结果集中包含的记录数。如果您连接两个物理表(子查询不是物理表),则数据库可以通过可用统计信息轻松确定两个结果集中的数据量。如果其中一个结果集是一个子查询,那么要了解它返回的记录数是非常困难的。在这种情况下,数据库可以选择错误的连接查询计划,这样会导致查询性能大幅下降。
使用临时表重写查询旨在简化数据库优化器。在重写查询中,参与连接的所有结果集都是物理表,数据库将很容易确定每个结果集的长度。这将允许数据库选择所有可能的查询计划中保证最快的。而且,无论条件如何,数据库都会做出正确的选择。使用临时表的重写查询可以在任何数据库上很好地工作,这在便携式解决方案的开发中尤为重要。此外,重写的查询更易于阅读,更易于理解和调试。
据了解,使用临时表重写查询可能会因额外费用而导致一些减速:创建临时表。如果数据库不会被错误地选择查询计划,它将比新查询更快地执行旧查询。但是,这种放缓总是可以忽略不计。通常,创建临时表需要几毫秒。也就是说,延迟不会对系统性能产生重大影响,通常可以忽略不计。
重要!不要忘记为临时表创建索引。索引字段应包括在连接条件中使用的所有字段。
答案 1 :(得分:9)
这里有很多事情需要解决,索引,执行计划等。测试和比较结果是可行的方法。
您可以查看通常的嫌疑人,索引。查看执行计划并进行比较。确保WHERE
子句使用正确的子句。确保您使用JOINs
上的索引。
这些答案肯定会对你有所帮助。