對聚集表查詢的時候,未顯式指定排序列的時候,默認查詢結果的順序一定是按照聚集索引順序排序的嗎


本文之外可參考另外一篇文章作為補充:http://www.cnblogs.com/wy123/p/6189100.html

 

在sql server 中,如果一張表存在聚集索引的時候,
大多數情況下,如果進行select * from TableName查詢,默認的返回順序是按照聚集所在列的順序返回的
但是,在一張表存在聚集索引的時候,並不一定所有的情況都是按照聚集索引列的順序排列的,
下面開始測試

create table TestDefaultOrder
(
	Id int identity(1,1) primary key,--主鍵上默認會建立聚集索引
	Col2 char(5),
	COL3 char(5)
)
--寫入100000條測試數據
insert into TestDefaultOrder  values (SUBSTRING(cast(NEWID() as varchar(50)),1,5),SUBSTRING(cast(NEWID() as varchar(50)),1,5))
go 100000

如下查詢完全沒有問題,正如你所預料的,按照聚集索引所在的列(Id)排序的,完全沒有問題,下面開始切入正題

 

--創建一張同樣的對照表
create table TestDefaultOrder_Contrast
(
	Id int identity(1,1) primary key,--主鍵上默認會建立聚集索引
	Col2 char(5),
	COL3 char(5)
)

--將TestDefaultOrder表中的數據寫入進去,目前,兩張表的數據和索引結構一模一樣
insert into TestDefaultOrder_Contrast (Col2,Col3)  
select Col2,Col3 from TestDefaultOrder

--僅僅在對照表上創建一個非聚集索引,這是唯一的不同點
Create Index idx2 on TestDefaultOrder_Contrast(Col2,Col3)

接下來的查詢,或許會有一點一點出乎你的意料,

上面說了,兩張表的數據是一模一樣的,聚集索引結構也是一樣的,只是對照表多個一個非聚集索引

發現對照表的結果返回順序,根本是按照聚集索引的排序返回的

 

那么原因在哪里呢?我們要從不同類似索引占用的空間情況進行分析,通過dm_db_index_physical_stats發現,在數據數據完全一致的情況下,

因為TestDefaultOrder_Contrast這個表上的非聚集索引,占用的空間更少(248個page,而TestDefaultOrder的聚集索引是285個page),

正因為此,sqlserver在進行全表掃描的時候,會選擇一個代價更小的索引(進行掃描),

因為TestDefaultOrder表上只有一個聚集索引,按照聚集索引掃描進行查詢,返回的結果的順序是按照聚集索引列排序的

但是TestDefaultOrder_Contrast就不同了,因為在非聚集索引idx2 上,包含了全部的數據(Col2,Col3以及指向聚集索引鍵值的Id),

但idx2這個索引是占用的空間更小,所以對於TestDefaultOrder_Contrast的查詢,是按照idx2這個非聚集索引進行掃描的

 

因為,在TestDefaultOrder_Contrast這個表上,

直接select * TestDefaultOrder_Contrast進行查詢的話,

跟對表TestDefaultOrder進行 select * TestDefaultOrder查詢

是用兩種完全不同的方式進行的,出來的結果自然也就不同了

 

 

而事實上,sqlserver在對TestDefaultOrder_Contrast進行查詢的時候,通過走idx2這個索引掃描,代價確實要比TestDefaultOrder的聚集索引掃描,代價要小

 

如果有興趣的話,再次分析為什么存儲同樣的數據(TestDefaultOrder上的聚集索引和TestDefaultOrder_Contrast的非聚集索引idx2),

TestDefaultOrder表上的聚集索引,要比TestDefaultOrder_Contrast上的idx2(Create Index idx2 on TestDefaultOrder_Contrast(Col2,Col3))占用的空間大呢

這里的原因在於,一個表上的聚集索引(於非聚集索引相比),除了要存儲數據,要維護的信息更多的元數據信息,占用的空間自然就較多一點

而sqlserver在進行查詢的時候,總是會選擇一個代價相對較低的方式。

 

總結:千萬不要以為,只要表上建立了聚集索引,在查詢的時候,返回結果的默認的排序方式,是按照聚集索引來的

 

 

 

后記:為什么要研究這個問題?

因為之前遇到過,某些查詢沒有顯式指定排序列,但是借助表上聚集索引,返回結果的時候,會得一個想要的順序。

這種情況其實會潛在一種問題,如果發生類似上面這種情況,想要對查詢結果按照聚集索引的順序排序,而又不顯式制定排序列,查詢結果的顯示順序,可就不一定了。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM