48

这是关于 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 加入。

现在让我感到困惑的是,第一季度花了 > 2 分钟,(尝试了几次,以避免缓存发挥作用)而第二季度(两个查询相结合)花了 2 秒!!!是什么赋予了?

4

2 回答 2

63

为什么不建议使用子查询?

数据库优化器(无论您使用什么数据库)不能始终正确优化此类查询(带有子查询)。在这种情况下,优化器的问题是选择正确的方法来连接结果集。有几种算法可以连接两个结果集。算法的选择取决于包含在一个结果集中和另一个结果集中的记录数。如果连接两个物理表(子查询不是物理表),数据库可以通过可用的统计数据轻松确定两个结果集中的数据量。如果其中一个结果集是子查询,那么要了解它返回多少条记录是非常困难的。在这种情况下,数据库可能会选择错误的join查询计划,从而导致查询性能急剧下降。

使用临时表重写查询旨在简化数据库优化器。在重写查询中,所有参与连接的结果集都是物理表,数据库将很容易确定每个结果集的长度。这将允许数据库选择所有可能的查询计划中保证最快的。而且,无论条件如何,数据库都会做出正确的选择。使用临时表重写的查询在任何数据库上都可以很好地工作,这在可移植解决方案的开发中尤其重要。此外,重写后的查询更易于阅读、更易于理解和调试。

据了解,使用临时表重写查询可能会由于额外费用而导致一些速度变慢:创建临时表。如果数据库不会在查询计划的选择上出现错误,它将比新查询更快地执行旧查询。但是,这种放缓总是可以忽略不计。通常,临时表的创建需要几毫秒。即延迟不能对系统性能产生重大影响,通常可以忽略不计。

重要的!不要忘记为临时表创建索引。索引字段应包括连接条件中使用的所有字段。

于 2013-05-27T09:26:44.187 回答
11

这里有很多事情要解决,索引,执行计划等。测试和比较结果是要走的路。

你可以看看通常的嫌疑人,索引。查看执行计划并进行比较。确保WHERE子句使用正确的子句。确保您使用的是JOINs.

这些答案肯定会对你有很大帮助。

于 2013-05-27T07:24:35.117 回答