2016-11-05 71 views
1

我有一個大致包含1,000,000行,由約10萬條記錄成長下面的「PriceData」數據庫表/日:SQL服務器,請選擇要及時返回最新的紀錄

Id | DateCreated |TradeDate  |fk_Currency | Price 
-------------------------------------------------------------- 
48982| YYYYMMDDhhmmss | YYYYMMDDhhmmss |1   | 1.09684 
48953| YYYYMMDDhhmmss | YYYYMMDDhhmmss |1   | 1.22333 
48954| YYYYMMDDhhmmss | YYYYMMDDhhmmss |2   | 1.22333 

我要求的任務我一定要能夠獲取最新的價格對於一個給定的貨幣輸入,下面的存儲過程實現了這一點,但花費太長時間來執行(3.4秒):

PROCEDURE [dbo].[GetRecentPrice] @currency nvarchar(6) 
SELECT Price from PriceData 
WHERE Id = (SELECT MAX(Id) FROM PriceData 
    WHERE fk_CurrencyPair = (SELECT Id FROM CurrencyPair WHERE Name = @currency)); 

SQL Server的執行時間:CPU時間= 78毫秒,經過時間= 3428毫秒。

我試過,包括下面的where子句只檢查數據的前一分鐘:

AND TradeDate >= (SELECT (DATEADD(MINUTE, -1, (SELECT CONVERT(datetime, SYSDATETIMEOFFSET() AT TIME ZONE 'Central Standard Time')))) 

但它只有大約700毫秒帶來的執行時間下來:

CPU時間= 62毫秒,經過時間= 2762毫秒。

我也考慮過創建一個只存儲每種貨幣最近價格的新表格,只要PriceData表格中有新的價格就更新。但是,這感覺像一個骯髒的黑客攻擊,我肯定違反了一些數據庫規範化原則。

該存儲過程由一個MVC應用程序使用的Web服務層執行,因此執行時間需要更好(我想讓它達到< 100毫秒)。我願意修改此表和數據庫的體系結構。

回答

1

您可以嘗試使用TOP 1JOIN,看看它是如何比較原始查詢:

PROCEDURE [dbo].[GetRecentPrice] @currency nvarchar(6) 
SELECT TOP 1 t1.Price 
FROM PriceData AS t1 
JOIN CurrencyPair AS t2 ON t1.Id = t2.Id 
WHERE t2.Name = @currency 
ORDER BY t1.Id DESC 

你也應該把指數上都PriceDataCurrencyPairId領域。

+0

謝謝。關於指數; SQL Server默認在相應的主鍵上包含聚簇索引。這些索引是否足夠用於我的用例? – slashNburn

+1

@slashNburn yup,如果你已經在ID字段上創建了主鍵,那麼已經在該字段上創建了聚集索引。但是,如果將排序順序設置爲「DESC」,則不需要使用order by子句,只需將id字段置於select語句中即可。 – Shell

+0

@Giorgos Betsos:非常感謝你對這個非常優雅的答案的幫助。 SQL Server執行時間: CPU時間= 0毫秒,經過時間= 2毫秒 – slashNburn

0

你試過類似的東西嗎?

PROCEDURE [dbo].[GetRecentPrice] @currency nvarchar(6) 
SELECT TOP 1 p.Price from PriceData p 
JOIN CurrencyPair c ON p.fk_CurrencyPair = c.Id 
WHERE c.Name = @currency 
ORDER BY p.Id DESC;