Sql-Server

SQL Server:行順序

  • September 26, 2017

我們都知道一個簡單的語句如:

SELECT * FROM stuff;

不應產生有序的結果。然而,當我試圖證明這一點時,它總是以主鍵順序出現。

此外還有一個聲明,例如:

SELECT thing,whatever FROM stuff
GROUP BY thing,whatever;

似乎總是按GROUP BY子句中的最後一個欄位對事物進行排序,這根本沒有幫助。

問題是,在什麼情況下 SQL SERVER 會在未詢問的情況下對結果進行排序,我能做些什麼來阻止這種情況?

我試圖向我的學生證明,除非指定,否則訂單是不確定的,但這對我的情況沒有幫助。

我承認我正在處理一小組樣本數據。

謝謝

即使未詢問,SQL SERVER 在什麼情況下也會對結果進行排序?

如果檢索數據的訪問路徑恰好產生已排序的數據,例如按鍵順序進行索引掃描,則可能會發生這種情況。或者,如果計劃包含顯式排序,以便為需要此操作的操作員提供數據,例如合併連接或流聚合。如果沒有明確的order by順序,則無法保證,但 SQL Server 也不會竭盡全力阻止結果按順序輸出。

我能做些什麼來阻止這種情況?

對於第一個查詢,如果 SQL Server 使用分配順序掃描,您可以看到不同的順序。

因此,請確保表的大小至少為 64 頁,並且分配順序與鍵順序不同,然後以未送出的讀取隔離級別執行查詢。

CREATE TABLE T
(
X INT IDENTITY PRIMARY KEY,
Y CHAR(4000)
);

INSERT INTO T
SELECT TOP 100 'A'
FROM master..spt_values;

/* Cause page splits so key order and allocation order differ
  and leaves one row per page so table is now > 64 pages*/
ALTER TABLE T ALTER COLUMN Y CHAR(4001);

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;

SELECT *
FROM T;

在採用表鎖的情況下,上述情況不需要讀取未送出,有一個提示,但不太明顯的方法是將上面的表定義更改為

CREATE TABLE T
(
X INT IDENTITY PRIMARY KEY WITH(allow_row_locks = off, allow_page_locks = off),
Y CHAR(4000)
);

然後希望您無需更改隔離級別即可看到無序的結果。

對於第二個查詢,您需要雜湊聚合而不是流聚合。您可以通過查詢提示或不太明顯的計劃指南強制執行此操作,但如果與表的大小相比,不同的組相對較少,則更有可能有機地選擇。

Conor Cunningham(Microsoft 的 SQL Server 引擎軟體架構師)的這篇文章應該可以回答您的問題:

以下部分摘錄:

這裡的難點在於,任何外部使用者都沒有合理的方法知道計劃何時會改變。所有計劃的空間都很大,思考起來會讓人頭疼。如果有足夠多的參數更改,SQL Server 的優化器將更改計劃,即使對於簡單查詢也是如此。您可能很幸運並且沒有更改計劃,或者您可以不考慮這個問題並添加一個ORDER BY.

$$ … $$ 在很多情況下,優化器中的計劃可能會發生變化——對於更複雜的查詢,可能有數千個或更多的計劃選擇,並且每個都有可能被選中的情況。對於這些計劃中的每一個,如果您不指定,該計劃的排序可能會有所不同。

所以,我今天的建議是:

如果您需要在查詢結果中排序,請輸入ORDER BY. 就是這麼簡單。其他任何事情都就像在沒有安全帶的情況下乘坐汽車一樣。

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