Sql-Server

使用 STATS_STREAM 或 WITH FULLSCAN 更新統計資訊?

  • November 25, 2019

創建統計的語法是:

-- Syntax for SQL Server and Azure SQL Database  

UPDATE STATISTICS table_or_indexed_view_name   
   [   
       {   
           { index_or_statistics__name }  
         | ( { index_or_statistics_name } [ ,...n ] )   
               }  
   ]   
   [    WITH   
       [  
           FULLSCAN   
             [ [ , ] PERSIST_SAMPLE_PERCENT = { ON | OFF } ]    
           | SAMPLE number { PERCENT | ROWS }   
             [ [ , ] PERSIST_SAMPLE_PERCENT = { ON | OFF } ]    
           | RESAMPLE   
             [ ON PARTITIONS ( { <partition_number> | <range> } [, ...n] ) ]  
           | <update_stats_stream_option> [ ,...n ]  
       ]   
       [ [ , ] [ ALL | COLUMNS | INDEX ]   
       [ [ , ] NORECOMPUTE ]   
       [ [ , ] INCREMENTAL = { ON | OFF } ] 
       [ [ , ] MAXDOP = max_degree_of_parallelism ] 
   ] ;  

<update_stats_stream_option> ::=  
   [ STATS_STREAM = stats_stream ]  
   [ ROWCOUNT = numeric_constant ]  
   [ PAGECOUNT = numeric_contant ]

這裡有一個Martin Smith編寫的優秀腳本它使用 STATS_STREAM 編寫統計數據

當我在我的一個測試數據庫中執行該腳本時,我得到以下資訊:

DECLARE @Schema             sysname,
       @Table              sysname,
       @StatsName          sysname,
       @IncludeStatsStream BIT,
       @StatsStream        VARCHAR(MAX),
       @TwoPartQuotedName  NVARCHAR(500);

select  @Schema           = 'dbo',
       @Table            = 'tbl_Application_Medical',
       @StatsName        = '_WA_Sys_00000002_7039AB57',
       @IncludeStatsStream = 1;

select @TwoPartQuotedName = QUOTENAME(@Schema) + '.' + QUOTENAME(@Table);


IF @IncludeStatsStream = 1 AND @@MICROSOFTVERSION/ POWER(2,24) > 9
 BEGIN
     DECLARE @StatsResults TABLE
       (
          StatsStream VARBINARY(MAX),
          Rows        BIGINT,
          DataPages   BIGINT
       );

     INSERT INTO @StatsResults
     EXEC sys.sp_executesql 
       N'DBCC SHOW_STATISTICS(@TwoPartQuotedName, @StatsName) WITH STATS_STREAM;',
       N'@TwoPartQuotedName NVARCHAR(500), @StatsName sysname',
       @TwoPartQuotedName = @TwoPartQuotedName,
       @StatsName = @StatsName;

     --Would need some other method on 2005 hence just skipping this
     SELECT @StatsStream = CONVERT(VARCHAR(MAX), StatsStream, 1)
     FROM   @StatsResults;
 END;

WITH stats AS
(
/* 
Support earlier versions without these columns using trick from http://dba.stackexchange.com/a/66755/3690 */
SELECT x.*
FROM (SELECT NULL AS filter_definition, NULL AS is_incremental) AS dummy
CROSS APPLY
(
 SELECT object_id, stats_id, name, no_recompute, filter_definition, is_incremental
 FROM sys.stats
) AS x
)
SELECT '
CREATE STATISTICS ' + QUOTENAME(name) + '   
ON ' + @TwoPartQuotedName + ' (' + SUBSTRING(cols, 2, 10000000) +')
'  + 
ISNULL(' WHERE ' + filter_definition,'') +
ISNULL(STUFF ( 
   ISNULL(',STATS_STREAM = ' + @StatsStream, '') +
   CASE WHEN no_recompute = 1 THEN ',NORECOMPUTE' ELSE '' END + 
   CASE WHEN is_incremental = 1 THEN ',INCREMENTAL=ON' ELSE '' END
, 1 , 1 ,  ' WITH '  ) , '') AS [processing-instruction(x)]
FROM   stats s
      CROSS APPLY (SELECT ',' + QUOTENAME(c.name)
                   FROM   sys.stats_columns sc
                          JOIN sys.columns c
                            ON c.object_id = sc.object_id
                               AND c.column_id = sc.column_id
                   WHERE  sc.object_id = s.object_id
                          AND sc.stats_id = s.stats_id
                   ORDER  BY sc.stats_column_id
                   FOR XML PATH(''))CA(cols)
WHERE  s.object_id = OBJECT_ID(@TwoPartQuotedName)
      AND s.name = @StatsName
FOR XML PATH('');

select * from @StatsResults

一個xml文件:

<?x CREATE STATISTICS [_WA_Sys_00000002_7039AB57] ON [dbo].[tbl_Application_Medical] ([Smoker]) WITH STATS_STREAM = lot of binary chars that would not fit here?>

在此處輸入圖像描述

更新伺服器中所有數據庫所有表的統計資訊時, 我會從使用 stats_scream 而不是生成創建統計資訊WITH FULLSCAN腳本中受益嗎?

這兩個有什麼區別?

另一個答案是正確的,所以以防萬一一個例子讓事情更清楚……

CREATE TABLE T1
(
C1 VARCHAR(50),
INDEX CIX CLUSTERED(C1)
);

INSERT INTO T1
VALUES ('orange'), ('kiwi'), ('strawberry');


UPDATE STATISTICS [dbo].[T1]([CIX]) 
WITH STATS_STREAM = 0x01000000010000000000000000000000368684C40000000051020000000000001102000000000000A7020000A7000000320000000000000008D000000000000007000000009BA10039AA000003000000000000000300000000000000000000000000003F000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000020000000100000010000000ABAAAA400000404000000000ABAAAA4000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001304000000000000000000000000000049000000000000008D0000000000000095000000000000009D0000000000000010000000000000002C000000000000003000100000000040000000000000803F04000001001C006170706C65300010000000803F000000000000803F04000001001D0062616E616E61FF01000000000000000300000002000000280000002800000000000000000000000B0000006170706C6562616E616E61030000004000000000820500000001060500000003000000000000000000000000000000, 
ROWCOUNT = 3, PAGECOUNT = 1

DBCC SHOW_STATISTICS ( T1 , CIX )  WITH HISTOGRAM;   

統計數據完全是虛構的,與表格內容無關。它只是使用編碼在STATS_STREAM

+--------------+------------+---------+---------------------+----------------+
| RANGE_HI_KEY | RANGE_ROWS | EQ_ROWS | DISTINCT_RANGE_ROWS | AVG_RANGE_ROWS |
+--------------+------------+---------+---------------------+----------------+
| apple        |          0 |       2 |                   0 |              1 |
| banana       |          0 |       1 |                   0 |              1 |
+--------------+------------+---------+---------------------+----------------+

UPDATE STATISTICS [dbo].[T1]([CIX]) 
WITH FULLSCAN 

DBCC SHOW_STATISTICS ( T1 , CIX )    WITH HISTOGRAM; 

掃描所有基表行並創建具有正確值的新直方圖

+--------------+------------+---------+---------------------+----------------+
| RANGE_HI_KEY | RANGE_ROWS | EQ_ROWS | DISTINCT_RANGE_ROWS | AVG_RANGE_ROWS |
+--------------+------------+---------+---------------------+----------------+
| kiwi         |          0 |       1 |                   0 |              1 |
| orange       |          0 |       1 |                   0 |              1 |
| strawberry   |          0 |       1 |                   0 |              1 |
+--------------+------------+---------+---------------------+----------------+

STATS_STREAM選項僅對調試有用。它允許您將直方圖從生產複製到開發實例,而無需複制任何數據。這可以在嘗試評估查詢計劃問題時提供幫助。

引用自:https://dba.stackexchange.com/questions/235517