我們需要您的查詢的表格示例的詳細信息,以充分解決這個問題,但是:
- 日期時間列應自行高度選擇性,因此與
TimeOperation
指數作爲第一列應解決針對TimeOperation
的大部分查詢。
- 不要盲目地將所有列添加到索引或甚至包含索引 - 這會使索引頁面密度變差併產生反效果(您將在索引中複製表)。
- 如果數據庫中的所有數據都以
TimeOperation
爲中心,那麼可以考慮圍繞它構建聚簇索引。
- 如果您只對
field1 = x
有疑問,那麼您需要一個單獨的索引,僅用於field1
(假設它具有適當的選擇性),即索引上不存在TimeOperation
(如果它不在查詢的WHERE子句中)。
- 是的,當然,當SQL在索引中查找記錄時,它需要執行一個鍵(或RID)lookup back into the cluster來檢索其餘列。如果您的非聚集索引包含
select
語句中的其他列,則可以避免查找。但由於您使用的是SELECT(*),因此覆蓋索引不太可能有所幫助。
編輯
解釋 - 選擇性和密度進行詳細here說明。例如如果針對TimeOperation
的查詢僅返回少量行(經驗法則爲< 5%,但並非總是如此),那麼索引是否會被使用,即您的查詢是否具有選擇性,足以讓SQL選擇TimeOperation
上的索引。
的基本出發點是:
CREATE TABLE [MyTable]
(
intID INT ID identity(1,1) NOT NULL,
field1 NVARCHAR(20),
-- .. More columns, which may be selected, but not filtered
TimeOperation DateTime,
CONSTRAINT PK_MyTable PRIMARY KEY (IntId)
);
的基本指標進行
CREATE NONCLUSTERED INDEX IX_MyTable_1 ON [MyTable](TimeOperation);
CREATE NONCLUSTERED INDEX IX_MyTable_2 ON [MyTable](Field1);
聚類審議/選項
如果大部分的記錄插入以'串行'升序的TimeOperation順序,即intId和TimeOpe配給量將同時增加,那麼我將離開intID(默認值)(即,表DDL是PRIMARY KEY CLUSTERED (IntId)
,這是默認情況下)。
但是,如果有NOIntId
和TimeOperation
,並且IF大部分的查詢的形式是SELECT * FROM [MyTable] WHERE TimeOperation between xx and yy
然後CREATE CLUSTERED INDEX CL_MyTable ON MyTable(TimeOperation)
(和不斷變化的PK到PRIMARY KEY NONCLUSTERED (IntId)
)應改善查詢(基本原理之間的相關性:因爲連續次保持在一起,需要讀取更少的頁面,並且書籤查找將被避免)。更好的是,如果TimeOperation
的值保證是唯一的,那麼CREATE UNIQUE CLUSTERED INDEX CL_MyTable ON MyTable(TimeOperation)
將提高密度,因爲它將避免唯一性。
注 - 對於這個答案的其餘部分,我假設你IntId
和TimeOperations
是強相關的,因此集羣是由IntId
。
覆蓋索引
正如其他人所說,你的SELECT (*)
使用是不好的做法和尤其手段覆蓋索引將不會有任何使用(唯一的例外是COUNT(*)
)的。 如果您的查詢不是SELECT(*),而是例如
SELECT TimeOperation, field1
FROM
WHERE TimeOperation BETWEEN x and y -- and returns < 5% data.
然後改變上TimeOperation
索引以包括field1
CREATE NONCLUSTERED INDEX IX_MyTable ON [MyTable](TimeOperation) INCLUDE(Field1);
OR同時添加到索引(第一,最常見的過濾器,或最有選擇性的第一,如果兩個濾波器總是存在)
CREATE NONCLUSTERED INDEX IX_MyTable ON [MyTable](TimeOperation, Field1);
要麼會避免rid/key查找。第二個(,)選項將解決您的查詢,其中BOTH TimeOperation和Field1在WHERE或HAVING子句中被過濾。
回覆:索引(TimeOperation,Field1)和單獨索引之間有什麼區別?
例如
CREATE NONCLUSTERED INDEX IX_MyTable ON [MyTable](TimeOperation, Field1);
不會對查詢有用
SELECT ... FROM MyTable WHERE Field1 = 'xyz';
該指數將只針對有TimeOperation
SELECT ... FROM MyTable WHERE TimeOperation between x and y;
OR
SELECT ... FROM MyTable WHERE TimeOperation between x and y AND Field1 = 'xyz';
希望這個查詢有用幫助?
「'select *'因爲或多或少我需要所有的字段。」這不是一個很有說服力的理由。想象一下,如果其中一列是「varchar(max)」,其中每行存儲1GB文檔。如果你沒有*使用那個欄目,那麼很多浪費資源來檢索它們。即使目前情況不是這樣,如果這樣的一列在6個月後被添加了,該怎麼辦?突然間,所有人「'select *'因爲我需要大多數列」查詢變得非常慢。 –
SELECT *很懶。請閱讀這篇文章,其中包括一個解決方法,無需執行所有耗時的指關節式打字工作(只刪除不需要的列):http://sqlblog.com/blogs/aaron_bertrand/archive/2009 /10/10/bad-habits-to-kick-using-select-omitting-the-column-list.aspx –
對不起,我表達得很糟糕,我並不是說我使用「select *」,我只提取了我需要在不同的查詢中使用列。我的意思是,在每個查詢中,我使用日期時間範圍,並考慮所有查詢,我請求所有列......我的意思是:對於性能解決方案,我需要專注於如何更好地排序日期時間 –