2013-11-10 24 views
0

我有一個多對多的鏈接表CategoryProduct 2列,這將有幾百萬條記錄:SQL Server查詢性能,複合材料領域

CREATE TABLE [dbo].[CategoryProduct](
[Category_ID] [int] NOT NULL, 
[Product_ID] [int] NOT NULL, 
CONSTRAINT [PK_dbo.CategoryProduct] PRIMARY KEY CLUSTERED 
(
    [Category_ID] ASC, 
    [Product_ID] ASC 
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 

基於聚集索引,我預計看到物理記錄存儲在以下結構:

CategoryID ProductID 
1    2 
1    3 
2    1 
2    3 

然而,與選擇的結果是

CategoryID ProductID 
2    1 
1    2 
1    3 
2    3 

爲什麼數據存儲在ProductID組中?這是否反映數據的實際順序?如何將數據保存在CategoryID組中,以便在匹配的CategoryID被擊中時,可以使用連續閱讀來優化如下的查詢。

select ProductID from CategoryProduct where CategoryID = value 
+0

你爲什麼不按類別ID排序? –

+0

@DoobyInc我更新了我的問題。 – mortdale

+0

你只是想通過類別ID或其他東西?如果你只是想按類別ID排序,那你爲什麼不在SQL的select語句的最後使用關鍵字的順序? –

回答

3

當SQL Server取做表掃描或聚集索引掃描 (如果你的表是羣集), 數據可能選擇跟隨葉頁面,因爲搜索指定參數時,鎖提示和其他參數的鏈接,也可能請遵循索引分配映射,由於發生頁面拆分,大多數情況下索引分配映射的順序並不相同。

使用聚集索引不是速度的保證時,SQL Server計算不同 的方式爲每個請求檢索數據,即使是簡單的請求(SQL查詢優化器是一個非常複雜的系統)。

這不是以特定順序獲取數據的方法, 以特定順序獲取數據的唯一方法是在查詢 (這是ANSI規範)中指定ORDER BY子句。

如果你想提高性能,你應該研究你的請求的查詢計劃。 有幾種方法可以獲取請求的查詢計劃,最簡單的方法是在執行請求之前在Sql Magenement Studio工具欄中選擇「包含實際查詢計劃」按鈕。

後續操作: 帶有聚簇索引,數據按照聚簇定義的順序物理存儲,直到聚簇被分段。 ONLY在SELECT中按特定順序獲取數據的方法是向SELECT中添加ORDER BY子句,而不是創建索引。

+0

我想將數據存儲在CategoryID組中的原因是在匹配的CategoryID被擊中時連續讀取。假設CategoryID 1有2個ProductID爲1和10000000的產品,如果數據存儲在CategoryID組中,我只需要讀取前2條記錄即可獲得結果。 – mortdale

+0

@mortdale,您完全正確地將您的數據集羣在CategoryId,ProductId上。重點是,如果您不在SELECT中添加ORDER BY子句,即使它們「按該順序存儲」,在這些字段上創建集羣索引也不會保證您按順序獲取它們。 – ARA

+0

這是否意味着數據是根據聚集索引進行物理保存的?這只是我的選擇陳述不反映數據的實際順序? – mortdale

1

您不應該依賴聚簇鍵來排序數據。它按照聚簇鍵的順序存儲在磁盤上,但這並不意味着返回的數據是保證將以任何順序返回。如果您需要訂購數據,則需要使用ORDER BY條款。

您的查詢在索引的使用方面會很好。無論如何,訂購數據並不是驗證它的方法。您應該執行您的查詢,檢查執行計劃並確認索引確實被使用。

+0

我的問題是關於如何通過使用聚集索引來提高性能。然而,我創建的聚集索引並沒有給出我想要的結構。 – mortdale

+0

它以什麼方式沒有? – Szymon