sys.dm_db_partition_stats 上的簡單查詢執行了 30 分鐘
對使用者數據庫上 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’) 開始”
(為了避免長時間執行的評論執行緒(和保羅的憤怒;-),我把它作為一個可以詳細說明和擴展的答案。)