如何防止 RID 查找?
我有一個儲存時間序列數據的表,大約有 800 萬行。表結構如下:
時間戳 | 組件ID | 參數1 | 參數2 | 參數3
我在Timestamp和ComponentID列上有一個聚集索引。(這也是我的主鍵)
我要執行的查詢是:-
SELECT * FROM table WHERE Timestamp BETWEEN '2020-01-01' AND '2020-01-02' AND ComponentId = 5
當我執行此查詢時,似乎正在進行 RID 查找。我已經讀過這僅在索引不涵蓋所有內容時發生,但由於我有一個聚集索引,我認為它本身應該涵蓋所有內容並防止查找。如何防止這種查找發生?
RID 查找發生在 SQL Server 中的堆資料結構上(與B-Tree相對)。當使用非覆蓋非聚集索引來獲取數據並且它需要查找它失去的剩餘欄位時,就會發生這種情況。當該表上沒有聚集索引時,您的表數據儲存在堆中(因為聚集索引定義了記錄通常排序到B 樹中的順序)。
如果您的表有一個聚集索引並且該查詢想要使用它目前使用的同一個非聚集索引,那麼您會在****執行計劃中看到一個鍵查找操作。
如果您在表上為這兩個欄位創建了一個聚集索引
Timestamp
,ComponenentID
那麼這將覆蓋您的查詢,您應該會看到執行計劃中使用的聚集索引,這將消除任何類型的額外查找操作。關於評論中的第二個問題,根據您最近的評論更新,聽起來您看到的執行時差異是由於第一次執行將數據從磁碟拉入****記憶體(這通常是該過程中最瓶頸的部分,從硬體的角度來看)和第二次執行利用記憶體中的現有數據。
根據您的表和頁面大小有多大,這通常不應該太令人擔憂(基於我看到您的查詢從其執行計劃返回的行數)。查詢的所有後續執行(當數據仍在記憶體中時)將具有最佳性能。
如果從磁碟上提取數據的初始執行出現問題,那麼您可以查看壓縮或分析是否可以將磁碟升級到更快的速度(不確定您目前是否仍在機械硬碟驅動器上,並且可以切換到SSD甚至更好的是NVMe)。
我還將在評論中添加最後一條註釋,該註釋是真實且相關的,但不是根本問題本身,即您的查詢對
ComponentId
結果進行額外過濾會導致讀取更多數據。如果您比較兩個查詢之間的邏輯讀取總數,這在您的IO 統計螢幕截圖中很明顯。一個查詢過濾並導致 396 Logical Reads而另一個查詢過濾僅導致 90 Logical Reads。邏輯讀取數是從記憶體中讀取的8 KB 頁數。****Physical Reads是8 KB Pages的數量Timestamp``ComponentId``Timestamp
從磁碟讀取的。這不是一個巨大的差異,但會導致在第一次執行時執行第一個查詢與第二個查詢之間的時間差異很小。當數據已經從磁碟儲存在記憶體中時(如我前面幾段中所討論的),這成為兩個查詢後續執行的一個有爭議的問題。