2011-10-31 57 views
1

查詢我在SQL Server下表:表的正確的索引給上市

CREATE TABLE [dbo].[Users](
    [Id] [int] IDENTITY(1,1) NOT NULL, 
    [Email] [varchar](128) NOT NULL, 
    [CreatedAt] [datetime] NOT NULL, 
    [SourceId] [int] NOT NULL 
PRIMARY KEY CLUSTERED 
(
    [Id] ASC 
) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 
) ON [PRIMARY] 

此表的成長空間很大的潛力。最頻繁的查詢運行在該表將是:

SELECT * FROM Users WHERE Email = '[email protected]' 
SELECT * FROM Users WHERE Email = '[email protected]' AND SourceId = some integer 
SELECT * FROM Users WHERE CreatedAt BETWEEN '2011-10-01' AND '2011-10-30' 
SELECT * FROM Users WHERE CreatedAt BETWEEN '2011-10-01' AND '2011-10-30' AND SourceId = some integer 

目前,我已經安裝了以下指標:

CREATE INDEX IX_Users_Email_SourceId ON Users (Email, SourceId) 
CREATE INDEX IX_Users_CreatedAt ON Users (CreatedAt) 
CREATE INDEX IX_Users_SourceId ON Users (SourceId) 

難道這些指標足以滿足上面列出的查詢的類型?如果這將是一個嚴重查詢的表,我應該將ALLOW_ROW_LOCKS = ON,ALLOW_PAGE_LOCKS = ON設置爲OFF嗎?我對如何正確設置索引有些困惑。

回答

1

我會對其進行索引是這樣的:

WHERE Email = '[email protected]' 
index: Email 
or Email, SourceId 

WHERE Email = '[email protected]' AND SourceId = some integer 
index: SourceId, Email 
or Email, SourceId 

WHERE CreatedAt BETWEEN '2011-10-01' AND '2011-10-30' 
index: CreatedAt 
or CreatedAt, SourceId 

WHERE CreatedAt BETWEEN '2011-10-01' AND '2011-10-30' AND SourceId = some integer 
index: SourceId, CreatedAt 
or CreatedAt, SourceId 

這是很難完全確定的這些,什麼是SourceId選擇性。根據這一點,您可以嘗試使用單個索引涵蓋多個查詢(前兩個可以合併,最後兩個可以合併)。如果SourceId是非常有選擇性的(少數行匹配每個值),我不想合併索引,並通過使用四個索引來實現最佳性能。另外,你沒有提到你期望有多少插入/更新,因此很難確定更多/更少索引的開銷會發揮多少。

此外,您的SELECT *使其不可能推薦覆蓋索引等。

+0

感謝KM。我應該關閉行和頁鎖嗎?或者這是一個壞主意? SourceId不會很有選擇性。會有很多INSERTS(但沒有那麼多UPDATES)。 – Thomas

+0

您擔心基於INSERT/UPDATE/DELETE頻率的鎖定以及它們事務的長度。如果你主要是經常選擇這個數據,而且交易時間不長,那麼在你開始出現問題之前,我不會擔心這些數據。 –