为什么临时表和子选择之间存在巨大的性能差异

War*_*ard 36 sql sql-server-2008-r2 query-performance

这是一个关于SQL Server 2008 R2的问题

到目前为止,我不是DBA.我是一名java开发人员,必须不时编写SQL.(主要嵌入代码中).我想知道我在这里做错了什么,如果是的话,我可以做些什么来避免它再次发生.

Q1:

SELECT something FROM (SELECT * FROM T1 WHERE condition1) JOIN ...
Run Code Online (Sandbox Code Playgroud)

Q1有14个连接

Q2与Q1相同,但有一个例外.(SELECT*FROM T1 WHERE condition1)之前执行,并存储在临时表中.

这不是相关的子查询.

Q2:

SELECT * INTO #tempTable FROM T1 WHERE condition1
SELECT something FROM #tempTable  JOIN ...
Run Code Online (Sandbox Code Playgroud)

再次,14加入.

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

Kar*_*AMR 49

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

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

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

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

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

  • SQL Server 查询引擎在内部创建临时表,上面提供的原因并不总是正确的。它取决于更多其他因素,如索引、碎片、统计等。 (2认同)
  • 在临时表上创建索引可提高查询性能. (2认同)
  • @GordonLinoff第一段和第二段的结论是应该用临时表重写子查询,因为:"数据库可以通过可用的统计信息轻松确定两个结果集中的数据量"这是一个错误的假设并且可能导致错误结论. (2认同)

Yar*_*lav 9

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

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

这些答案肯定会对你有所帮助.