Sql-Server

預讀和 SQL-Variant 欄位

  • November 15, 2016

我有兩個包含完全相同數據的表。兩個表都有bigint primary key identity column60 列和 300 000 行。不同之處在於第二個表的所有列都有sql-variant類型。

我正在創建臨時表並從其中的兩個表中導入數據。當從sql-variant列中提取數據時,它被轉換為相應的 SQL 類型。

從第一個表中提取數據是針對1 sec和從第二個表中提取的6 secs

基本上,執行的差異在於估計:

在此處輸入圖像描述

在此處輸入圖像描述

read-ahead reads計數中:

在此處輸入圖像描述 在此處輸入圖像描述

我想知道為什麼SQL Server不能提前載入從sql-variant欄位中讀取的數據(幾乎沒有read-ahead reads)。

此外,表的儲存大小幾乎相同:

在此處輸入圖像描述

為什麼SQL Server認為它應該閱讀67 GB


列類型為:

16 x BIGINT
8  x DECIMAL(9,2)
36 x NVARCHAR(100)

dbcc dropcleanbuffers命令每次在數據提取和填充之前使用。


為了進行測試,您可以從這裡下載範例數據文件。然後,

  1. 執行Tech05_01_TableDefinitions.sql
  2. 執行3次Tech05_02_TablePupulation.sql
  3. 像這樣打開Tech05_03_TestingInsertionInTempTable.sql文件並執行一次:
DECLARE @TableStructured SYSNAME = '[dbo].[NormalDataTypes_60Cols]';
DECLARE @TableFromWhichDataIsCoppied SYSNAME = '[dbo].[SQLVariant01_60Cols]';

有一次像這樣:

DECLARE @TableStructured SYSNAME = '[dbo].[NormalDataTypes_60Cols]';
DECLARE @TableFromWhichDataIsCoppied SYSNAME = '[dbo].[NormalDataTypes_60Cols]';

Tech05_03_TestingInsertionInTempTable.sql 文件存在一些問題。它使用一個名為

$$ dbo $$.$$ ConcatenateWithOrder $$沒有定義。我想我理解了您的意圖並對其進行了調整以產生一些插入語句。 要回答您的第一個問題,SQL Server 不能使用預讀來獲取 sql_variant 數據是不正確的。如果我DBCC DROPCLEANBUFFERS;在插入之前立即執行,我會從統計資訊 io 中獲得以下輸出:

表“SQLVariant01_60Cols”。掃描計數 1,邏輯讀取 66311,物理讀取 3,預讀讀取 66307,lob 邏輯讀取 0,lob 物理讀取 0,lob 預讀讀取 0。

為了回答關於計劃中估計行大小的第二個問題,SQL Server 不會查看表使用的空間並除以行數。相反,查詢計劃包含基於表中數據類型的估計。有關更多詳細資訊,請閱讀Martin Smith 的這篇文章

SQL Server 估計您的表的行大小為 235 KB。我可以接近:

240484.0 = 0.5 * (8016 * 60 + 8)

這與 235 KB 相比略有偏差,但我不知道如何準確計算 sql_variants 的空間估計值。但是您可以看到,當使用可以儲存許多不同數據類型的數據類型時,您可能會被高估。作為記錄,我認為該估計與您觀察到的性能問題沒有任何關係。

為了回答我認為您想問的問題(為什麼使用 sql_variant 的查詢比其他查詢慢得多?),我對其進行了一些測試,從 sql_variant 表中進行選擇時似乎有很大的 CPU 成本。我選擇了行而不是插入它們(在它們到達客戶端之前將它們丟棄)並發現 cpu 時間存在顯著差異。sql_variant 查詢的 CPU 時間為 3151 毫秒,總執行時間為 3268 毫秒。另一個查詢的 CPU 時間為 686 毫秒,總執行時間為 744 毫秒。CPU 時間的差異幾乎完全解釋了執行時間的差異。

使用 sql_variant 列時出現成本似乎不是不合理的,對吧?我不知道有什麼技巧可以避免支付成本。如果您覺得您的數據模型需要 sql_variant 列,我只能建議進行測試以確保您可以獲得足夠好的性能。

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