論壇高頻提問:「同一查詢為什麼有時按預期順序返回,有時不按?SQL 2000 是這個順序,2005/2008 變了?」
SQL Server 查詢結果順序僅由
ORDER BY保證。無ORDER BY時,返回順序是未定義的,可能隨執行計劃、索引、並行度、統計信息、補丁版本任意變化。
| 誤區 | 真相 |
|---|---|
| 「表有叢集索引,插入順序就是查詢順序」 | 叢集索引決定物理存儲順序,但查詢優化器可選擇非叢集索引掃描、並行掃描、Hash Match 等,輸出順序不受存儲順序約束。 |
| 「加了非叢集索引覆蓋查詢,順序就固定了」 | 索引順序僅在優化器恰好選擇該索引且為順序掃描時體現;並行計劃、參數嗅探、統計更新均可能導致計劃變更、順序改變。 |
| 「SQL 2000 總是按主鍵順序,升級後亂了」 | 舊版優化器較簡單,巧合符合預期;新版優化器更激進,並行度更高,順序自然不同。這是正確行為,非 Bug。 |
| 「加個 TOP 100 PERCENT 就能排序」 | 無 ORDER BY 的 TOP 100 PERCENT 仍不保證順序;視圖/派生表中同理。 |
-- 永遠顯式指定 ORDER BY
SELECT Id, Name, CreateTime
FROM dbo.Orders
WHERE Status = 1
ORDER BY CreateTime DESC; -- 業務要求的順序
OFFSET/FETCH、ROW_NUMBER() OVER (ORDER BY ...) 強制要求 ORDER BY,這正是為了消除順序不確定性。
ORDER BY 列上建立索引(叢集或非叢集),避免顯式排序運算符。WHERE Key > @LastKey ORDER BY Key),無需全排序。ORDER BY (SELECT NULL) 可明確告訴優化器「不在乎順序」,有時能獲得更優計劃(罕用)。無 ORDER BY,無順序保證。 將此作為鐵律寫入編碼規範,Code Review 必查項。升級版本、遷移雲端、統計信息更新、參數嗅探觸發,任何環境變化都可能打破你觀察到的「巧合順序」。