2014-04-10 74 views
1

我們正在使用SQLServer 2008,並對許多表具有「只插入」模式。適用於「僅插入」模式的SQL服務器索引

的排序表中,我們已經是一個例子(這只是一個例子):

create table spotquotes 
(
    Id numeric(19,0) identity(1,1) not null primary key clustered, 
    feeditem_id numeric(19,0) not null, 
    value_ask float not null, 
    value_bid float not null, 
    effectiveDateUTC datetime not null default getutcdate() 
) 

我們則與此查詢

select * from spotquotes q 
inner join 
    (select feeditem_id, max(id) as latest from spotquotes group by feeditem_id) q2 
    on q.id = q2.latest and q.feeditem_id = q2.feeditem_id 

其實查詢表,它有必要創建上述查詢的觀點:

create view latestspotquotes as 
select * from spotquotes q 
inner join 
    (select feeditem_id, max(id) as latest from spotquotes group by feeditem_id) q2 
    on q.id = q2.latest and q.feeditem_id = q2.feeditem_id 

即我們想要的「最新」插入到表中的每個費ditem_id - 但我們也有能力查詢過去任何時候的表的狀態(這對於審計考慮非常好)。

一個更簡單的方法來說明。我希望優化以下查詢:

select feeditem_id, max(id) as latest from spotquotes group by feeditem_id 

此表通常有數億行的 - 但少數feeditem_id情況下,這很可能是在表的末尾的。

使用此表中的現有主鍵和約1億行,SQL Server 2008需要6秒鐘才能執行此查詢 - 速度非常慢。

所以我想知道 - 如果我們要爲這個表創建一個索引來加速這個查詢,我們應該創建什麼索引?

不幸的是,管理工作室並沒有爲我們建議索引。

編輯:仍有問題,但我會提出作爲一個單獨的問題。

UPDATE

更快的查詢(< 10毫秒)可以通過使用「交叉應用」連同選擇頂部* ... ORDER BY編號降序被哄騙了SQL服務器。詳細信息請參見Convincing SQL server to search backwards on clustered index for an insert only schema

+0

'(選擇feeditem_id,MAX(ID)的最新作ID)' - 你確定這是正確的? – dean

+0

您的嵌套查詢位於同一個表或不同的表上? – raholling

+0

raholling - 這是同一張桌子。 –

回答

0

對於此查詢:

select feeditem_id, max(id) as latest from spotquotes group by feeditem_id 

創建以下非聚集索引

CREATE INDEX IX_Spotquotes_feeditem_id on spotquotes(feeditem, id) 
+0

非常感謝主任 - 我現在就試試這個。小錯字應該是spotquotes(feeditem_id,id) –

+0

不幸的是,雖然showplan_xml顯示它現在使用這個索引,它*仍然*需要5秒! –

+0

如果它是有序的索引掃描,就是這樣。你是否選擇了這兩個以外的其他列? – dean

1

僅插入索引:S我只是插入精簡插入模式最好不帶任何索引,但在表上有任何索引將會影響插入操作的性能。

什麼樣

CREATE NONCLUSTERED INDEX NIX_feeditem_id_effectiveDateUTC 
ON dbo.spotquotes(feeditem_id ASC, effectiveDateUTC DESC) 
GO 

,現在在創建和feeditem_id領域effectiveDateUTC的東西寫索引查詢類似.....

;WITH LastestRecords 
AS(
    SELECT Id 
     ,feeditem_id 
     ,value_ask 
     ,value_bid 
     ,effectiveDateUTC 
     ,ROW_NUMBER() OVER (PARTITION BY feeditem_id ORDER BY ffectiveDateUTC DESC) AS RN 
    FROM spotquotes 
) 
SELECT Id 
     ,feeditem_id 
     ,value_ask 
     ,value_bid 
     ,effectiveDateUTC 
FROM LastestRecords 
WHERE RN = 1 

OR

創建索引如下

CREATE NONCLUSTERED INDEX NIX_feeditem_id_Id 
ON dbo.spotquotes(feeditem_id ASC, ID DESC) 
GO 

查詢

;WITH LastestRecords 
AS(
    SELECT Id 
     ,feeditem_id 
     ,value_ask 
     ,value_bid 
     ,effectiveDateUTC 
     ,ROW_NUMBER() OVER (PARTITION BY feeditem_id ORDER BY Id DESC) AS RN 
    FROM spotquotes 
) 
SELECT Id 
     ,feeditem_id 
     ,value_ask 
     ,value_bid 
     ,effectiveDateUTC 
FROM LastestRecords 
WHERE RN = 1 
+0

'INSERT Only'是指你不執行'UPDATE'操作的事實。相反,您插入一條新記錄,保留舊記錄並使用業務邏輯來確定要從哪些記錄中選擇*(它們「當前有效」)*。 – MatBailie

+0

對。只需添加 - 正確索引ROW_NUMBER()意味着在'(partitioning_columns,order_by_columns)'上創建一個複合索引,可能包含更好性能的列,並且如果存在靜態WHERE子句,可能會對其進行過濾。 – dean

+0

我不太明白這是如何工作 - 但我想要一個答案,實現正確的查詢計劃*無需*必須更改SQL查詢...應該是可能的不應該嗎? –