Sql 为什么temp表和subselect之间存在巨大的性能差异

Sql 为什么temp表和subselect之间存在巨大的性能差异,sql,sql-server-2008-r2,subquery,query-performance,temp-tables,Sql,Sql Server 2008 R2,Subquery,Query Performance,Temp Tables,这是一个关于SQL Server 2008 R2的问题 到目前为止,我不是DBA。我是一名java开发人员,必须不时编写SQL。大部分嵌入在代码中。我想知道我在这里是否做错了什么,如果是的话,我能做些什么来避免它再次发生 问题1: Q1具有14个连接 Q2与Q1相同,但有一个例外。从T1中选择*,条件1在此之前执行,并存储在临时表中 这不是一个相关的子查询 问题2: 同样,14人加入 现在让我困惑的是,Q1花费了>2分钟,尝试了几次,以避免缓存发挥作用,而Q2两个查询加起来花费了2秒!!!给出了

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

到目前为止,我不是DBA。我是一名java开发人员,必须不时编写SQL。大部分嵌入在代码中。我想知道我在这里是否做错了什么,如果是的话,我能做些什么来避免它再次发生

问题1:

Q1具有14个连接

Q2与Q1相同,但有一个例外。从T1中选择*,条件1在此之前执行,并存储在临时表中

这不是一个相关的子查询

问题2:

同样,14人加入


现在让我困惑的是,Q1花费了>2分钟,尝试了几次,以避免缓存发挥作用,而Q2两个查询加起来花费了2秒!!!给出了什么?

这里有很多事情要处理,索引、执行计划等。测试和比较结果是一条路要走

你可以看看常见的嫌疑犯,索引。查看执行计划并进行比较。确保WHERE子句使用的是正确的。确保在联接上使用索引

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


为什么不建议使用子查询

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

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

可以理解的是,使用临时表重写查询可能会由于额外的开销(创建临时表)而导致某些速度减慢。如果数据库不会错误地选择查询计划,那么它执行旧查询的速度将比执行新查询的速度快。然而,这种放缓总是可以忽略不计的。通常,创建临时表需要几毫秒的时间。也就是说,延迟不会对系统性能产生显著影响,通常可以忽略


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

我的猜测是,条件1中的SELECT*FROM T1的估计行数非常不准确。将其具体化为一种诱人的方式意味着SQLServer确切地知道将返回多少行。您可以发布这两个实际执行计划的XML版本吗?SQL Server查询引擎在内部创建临时表,您上面提供的原因并不总是正确的。这取决于更多其他因素,如索引、碎片、,Statastics等。在临时表上创建索引可以提高查询性能。您的回答非常误导人,而且是错误的,只应在某些情况下考虑创建临时表:@Arvand。这没有错,尽管我不同意这个建议。如果您仔细阅读,Karthik和我都建议在临时表上使用索引来提高性能。根据我的经验,问题几乎总是嵌套的循环联接,通过查询提示可以避免这些问题。我发现查询提示比许多临时表更容易维护。@GordonLinoff第一段和第二段的结论是,子查询应该用临时表重写,因为:数据库可以通过可用的统计信息轻松确定两个结果集中的数据量,这是一个错误的假设,可以导致错误的结论。
SELECT something FROM (SELECT * FROM T1 WHERE condition1) JOIN ...
SELECT * INTO #tempTable FROM T1 WHERE condition1
SELECT something FROM #tempTable  JOIN ...