Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/27.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
SQL";加上;性能和临时表(可能需要“查询提示”来简化)_Sql_Sql Server_Tsql_Temp Tables - Fatal编程技术网

SQL";加上;性能和临时表(可能需要“查询提示”来简化)

SQL";加上;性能和临时表(可能需要“查询提示”来简化),sql,sql-server,tsql,temp-tables,Sql,Sql Server,Tsql,Temp Tables,给出以下示例查询(仅简化示例) 而且 DECLARE @DT int; SET @DT=20110717; BEGIN TRY DROP TABLE #LargeData END TRY BEGIN CATCH END CATCH; -- dump any possible table. SELECT * -- This is a MASSIVE table indexed on dt field INTO #LargeData -- put smaller results into tem

给出以下示例查询(仅简化示例)

而且

DECLARE @DT int; SET @DT=20110717;

BEGIN TRY DROP TABLE #LargeData END TRY BEGIN CATCH END CATCH; -- dump any possible table.

SELECT * -- This is a MASSIVE table indexed on dt field
INTO #LargeData -- put smaller results into temp
FROM mydata
WHERE dt=@DT;

WITH Ordered AS (
    SELECT TOP 10 * 
        , ROW_NUMBER() OVER (ORDER BY valuefield DESC) AS Rank_Number
    FROM #LargeData
)
SELECT * FROM Ordered
两者都产生相同的结果,这是一个基于字段数据的列表中的有限值和排名列表

当这些查询变得相当复杂时(更多的表、大量的条件、多个级别的“with”表等),底部查询的执行速度要比顶部查询快得多。有时速度会快20-100倍

问题是……

是否有某种查询提示或其他SQL选项会告诉SQL Server自动执行相同类型的优化,或者有其他格式会涉及更干净的aproach(尽量保持与查询1类似的格式)

请注意,“排名”或二次查询只是一个模糊的例子,实际执行的操作并不重要

这正是我所希望的(或类似的,但我希望这个想法是明确的)。请记住,下面的查询实际上不起作用

DECLARE @DT int; SET @DT=20110717;
WITH LargeData AS (
    SELECT * -- This is a MASSIVE table indexed on dt field
    FROM mydata
    WHERE dt=@DT
    **OPTION (USE_TEMP_OR_HARDENED_OR_SOMETHING) -- EXAMPLE ONLY**
), Ordered AS (
    SELECT TOP 10 * 
        , ROW_NUMBER() OVER (ORDER BY valuefield DESC) AS Rank_Number
    FROM LargeData
)
SELECT * FROM Ordered
编辑:重要的后续信息

如果在子查询中添加

 TOP 999999999      -- improves speed dramatically
您的查询的行为方式与在以前的查询中使用临时表类似。我发现执行时间几乎以完全相同的方式提高。这比使用临时表简单得多,基本上就是我想要的

然而

 TOP 100 PERCENT    -- does NOT improve speed
不以相同的方式执行(必须使用静态数字样式TOP 9999999)

说明:

从这两种格式的查询的实际执行计划中我可以看出(原始的一个具有正常的CTE,而每个子查询具有TOP 9999999)

普通查询将所有内容连接在一起,就好像所有表都在一个大规模查询中一样,这是预期的结果。过滤条件几乎应用于计划中的连接点,这意味着要同时计算和连接更多的行


在TOP 99999999版本中,实际执行计划将子查询与主查询明确分开,以便应用TOP语句操作,从而强制创建子查询的内存“位图”,然后将其连接到主查询。这看起来确实是我想要的,事实上它甚至可能更有效,因为具有大量RAM的服务器将能够完全在内存中执行查询,而无需任何磁盘IO。在我的例子中,我们有280 GB的RAM,比实际使用的内存还要多。

问题是,在第一个查询中,SQL Server查询优化器能够生成查询计划。在第二个查询中,由于要将值插入到新的临时表中,因此无法生成良好的查询计划。我猜在你看不到的地方正在进行一次全表扫描


在第二个查询中,您可能希望像以前一样将值插入#LargeData临时表,然后在“valuefield”列上创建一个非聚集索引。这可能有助于提高性能。

您不仅可以在临时表上使用索引,还可以使用统计信息和提示。我找不到能够使用CTE文档中的统计数据的参考资料,它特别指出您不能使用提示

当您拥有一个大数据集时,即使您不使用索引(很可能是因为它将使用统计数据来制定计划),临时表通常也是最有效的方法。我可能怀疑CTE的实现更像是表变量,而不是临时表

我认为最好的办法是看看执行计划有什么不同,以确定它是否是可以修复的


当您知道temp表的性能更好时,您反对使用它的具体原因是什么?

很可能是SQL针对错误的参数值进行了优化

有两种选择

  • 尝试使用
    选项(重新编译)
    。这样做是有代价的,因为它每次都会重新编译查询,但如果需要不同的计划,这可能是值得的

  • 您也可以尝试使用
    选项(针对@DT=somerepresentavievalue进行优化)
    问题是您选择了错误的值


  • 从SQL Server查询优化团队的博客中可以看到

    您可能需要查看执行计划来解决这些问题,但我很好奇,这是
    DECLARE@DT int;设置@DT=20110717
    实际上是您正在做的事情,或者是一个参数。这很重要,因为CTE可能会由于参数嗅探而执行不同的操作,而临时表似乎不是(以我的经验来看),您可能想看看这个问题,这正是我在服务器管理器中编写测试查询的方式。结果查询不以这种方式包含参数。在我的现实世界SQL中,它背后的实际逻辑可能太令人难以置信,难以理解,我已经查看了一些查询计划,它们往往非常庞大,以至于你真的无法理解瓶颈。在编辑之后,看起来就像是@MartinSmithYes。在许多情况下,我也会在临时表上创建索引,但你对这个例子的理解倒过来了。即使使用非索引的临时表,第二个查询也会执行第一个查询。这个例子可能不是,但在一个更复杂的例子中,它通常对性能有显著的好处(而且似乎没有任何负面影响)。我只倾向于在出现性能问题时使用临时表格式,这使它更具可读性。更简单的原因是,如果已经以另一种方式构建了这种类型的查询,那么就更容易发现它的哪些部分将受益。以单行或小行的形式下降
     TOP 100 PERCENT    -- does NOT improve speed