【问题标题】:SQL Server doesn't have the statistics for the table variable?SQL Server 没有表变量的统计信息?
【发布时间】:2017-03-16 02:43:34
【问题描述】:

我发现 MSDN 说“表变量没有统计信息”

https://msdn.microsoft.com/en-us/library/dd535534(v=sql.100).aspx

以下文章还说,即使在 SQL 2014 中,SQL Server 也不支持表变量的统计信息

“临时表很容易击败表变量,因为它们拥有统计信息的能力极大地改进了查询优化。SQL Server 2014 中的增强功能仍然如此。”

https://www.brentozar.com/archive/2014/04/table-variables-good-temp-tables-sql-2014/

然后我用 SQL Server 2014 做了一个测试,发现表变量的统计信息,所以在 SQL 2014 中,现在表变量有统计信息了,对吧?

USE tempdb;

DECLARE
@tb_table TABLE(
RowID INT IDENTITY(1,1) NOT NULL PRIMARY KEY
,ProductName NVARCHAR(50) NOT NULL UNIQUE
,Indate DATETIME NOT NULL  DEFAULT(GETDATE())
,index IX_Indate NONCLUSTERED (Indate)
);

DECLARE
@table_variable_id bigint
;
SELECT TOP 1 @table_variable_id = object_id
FROM tempdb.sys.all_objects AS A
WHERE parent_object_id = 0
ORDER BY create_date DESC

SELECT  
statistics_name = st.name
,table_name = OBJECT_NAME(st.object_id)
,column_name = COL_NAME(stc.object_id, stc.column_id)
FROM    tempdb.sys.stats AS st WITH(NOLOCK) 
    INNER JOIN tempdb.sys.stats_columns AS stc WITH(NOLOCK)
        ON st.object_id = stc.object_id  
        AND st.stats_id = stc.stats_id 
 WHERE st.object_id = @table_variable_id

顺便说一句,如果我们从上面的脚本中删除“,index IX_Indate NONCLUSTERED (Indate)”行,即使在 SQL2012 中,我们仍然可以在 SQL Server 的输出中看到两条统计记录。

【问题讨论】:

  • 我无法复制它。在我的测试中,@table_variable_id 是负数,sys.stats 只有正数 object_id
  • 您的 SQL Server 版本是 2014?如果我删除 ",index IX_Indate NONCLUSTERED (Indate) 行,该问题也可能发生在 SQL 2012 和 2014 中。
  • 我使用的是 SQL Server 2014 Express。 SELECT @@VERSION 返回“Microsoft SQL Server 2014 (SP1-CU7) (KB3162659) - 12.0.4459.0 (X64) 2016 年 5 月 27 日 15:33:17 版权所有 (c) Microsoft Corporation Express Edition (64-bit) o​​n Windows NT 6.1 (内部版本 7601:Service Pack 1)“。你用的是什么版本?
  • 我的版本是 Microsoft SQL Server 2014 - 12.0.4100.1 (X64) Apr 20 2015 17:29:27 版权所有 (c) Microsoft Corporation Enterprise Edition (64-bit) o​​n Windows NT 6.3 (内部版本 14393:)(管理程序)和 Microsoft SQL Server 2012 (SP3) (KB3072779) - 11.0.6020.0 (X64) 2015 年 10 月 20 日 15:36:27 版权所有 (c) Windows NT 上的 Microsoft Corporation Enterprise Edition(64 位) 6.3 (内部版本 14393:)(管理程序)
  • @VladimirBaranov - 您无法重现此问题的原因是因为最后一个查询需要在tempdb 的上下文中运行。这不是 EE 功能,也与后续版本中的不同基数猜测无关。或者与为表变量维护的行数有关。

标签: sql-server


【解决方案1】:

没有 SQL Server 不维护表变量的统计信息。

您的问题中的表变量有三个索引,SQL Server 将相应的三行插入sysidxstats

每个索引包含一行或表和索引视图的统计信息

这些行确实在status 列中设置了2 标志,表示它们用于统计,因此由sys.stats 返回,但没有相应的统计对象。

您可以使用the query here 看到这一点(需要通过 DAC 连接)

SELECT name,
       imageval
FROM   tempdb.sys.stats AS s
       INNER JOIN tempdb.sys.sysobjvalues AS o
               ON s.object_id = o.objid
                  AND s.stats_id = o.subobjid
WHERE  s.object_id = @table_variable_id; 

返回

+--------------------------------+----------+
|              name              | imageval |
+--------------------------------+----------+
| PK__#AD773B9__FFEE74513158C9C9 | NULL     |
| IX_Indate                      | NULL     |
| UQ__#AD773B9__DD5A978A62C2C478 | NULL     |
+--------------------------------+----------+

包含实际统计信息的imagevalNULL

这不是什么新鲜事。您在 2008 年也看到了相同的情况(尽管仅用于 PK 和 UQ,因为内联索引定义不能在那里使用)。

行计数的维护是单独完成的,不需要带有直方图的完整统计对象。这又不是什么新鲜事。

【讨论】:

    【解决方案2】:

    我在 Itzik Ben-Gan Improvements in Table Variables and Temporary Tables in SQL Server 2014 的这篇文章中找到了以下短语:

    使用 TF 2453 进行基数估计

    我将在本文中讨论的最后一项改进与表格有关 变量并且在 SQL Server 2014 RTM CU3 和 SQL 中可用 服务器 2012 SP2。您可以在此处找到描述它的支持条目。

    众所周知,SQL Server 不维护统计信息 比如表变量的直方图和密度向量。然而,SQL 服务器确实维护表中的行数,在某些情况下 在帮助优化器做出最佳选择方面大有帮助。

    您使用的是企业版。我认为这可以解释。 Kendra Little 的文章确实说企业版更智能。

    我会尝试与DBCC SHOW_STATISTICS 核对您看到的统计对象的详细信息,并确认它们是否具有正常统计对象具有的所有数据。为表变量创建的统计对象应该有较少的数据,例如,没有直方图。我手头没有要测试的企业版。

    【讨论】:

      猜你喜欢
      • 2021-12-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-23
      • 1970-01-01
      • 2018-01-13
      • 2011-05-06
      相关资源
      最近更新 更多