Sql-Server

sys.dm_db_partition_stats 上的簡單查詢執行了 30 分鐘

  • January 26, 2021

對使用者數據庫上 sys.dm_db_partition_stats 的簡單查詢執行了近 30 分鐘,而過去它在不到 5 秒的時間內完成。

查詢只是為了獲取正確的分區來載入數據,而不是從使用者數據庫中讀取任何數據。在任何其他大型使用者數據庫上,相同的查詢在不到 5 秒的時間內執行並完成。查看此數據庫的執行計劃和查詢輸出消息,我們觀察到一個表“sysrowsets”。掃描計數 1,邏輯讀取數為數十萬,而在其他數據庫上,它不到一千。

這是供參考的輸出。

表 ‘sysrowsets’。掃描計數 888,邏輯讀取 3227880,物理讀取 0,頁面伺服器讀取 0,預讀讀取 0,頁面伺服器預讀讀取 0,lob 邏輯讀取 0,lob 物理讀取 0,lob 頁面伺服器讀取 0,lob 讀取預讀為 0,lob 頁面伺服器預讀為 0。

我們無法直接查詢此 sysrowsets,因為它是一個基礎表。通過DAC連接時可以查詢,但從這裡找不到任何異常。

仍然想知道這麼多閱讀的原因是什麼,為什麼要花這麼長時間。

SQL Server 版本:2019,兼容級別:150

SELECT Max(pstats.partition_number) AS PartitionNumber
FROM sys.dm_db_partition_stats AS pstats(NOLOCK)
INNER JOIN sys.destination_data_spaces AS dds(NOLOCK) ON pstats.partition_number = dds.destination_id
INNER JOIN sys.partition_schemes AS ps(NOLOCK) ON dds.partition_scheme_id = ps.data_space_id
INNER JOIN sys.partition_functions AS pf(NOLOCK) ON ps.function_id = pf.function_id
LEFT JOIN sys.partition_range_values AS prv(NOLOCK) ON pf.function_id = prv.function_id
AND pstats.partition_number = (
CASE pf.boundary_value_on_right
WHEN 0
THEN prv.boundary_id
ELSE (prv.boundary_id + 1)
END
)
WHERE OBJECT_Name(pstats.object_id) = 'OBJECTNAME'
AND OBJECT_SCHEMA_NAME(pstats.object_id) = 'DBNAME'

查詢輸出強文本

我知道你從哪裡來。但是我認為如果不更改查詢,您將無法到達任何地方。這就是我們生活的世界,有優化器和我們得到的查詢計劃的不確定性。使謂詞可搜尋,您可能會得到一個不同的計劃,很可能會更好。在選擇 from 時,我在 object_id 上嘗試了不可搜尋謂詞與可搜尋謂詞sys.dm_db_partition_stats,並且確實得到了不同的執行計劃:

SELECT * FROM sys.dm_db_partition_stats
WHERE object_id  = 123132

SELECT * FROM sys.dm_db_partition_stats
WHERE CAST(object_id AS varchar(20))  = '123132'

因此,在第一條評論中重複丹尼斯的建議:“讓我們從更改 WHERE 子句 pstats.object_id = OBJECT_ID(N’SchemaName.TableName’) 開始”

(為了避免長時間執行的評論執行緒(和保羅的憤怒;-),我把它作為一個可以詳細說明和擴展的答案。)

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