SQL Server SELECT及时返回最新记录

时间:2016-11-05 16:18:03

标签: sql sql-server select stored-procedures

我有以下'PriceData'数据库表,其中包含大约1,000,000行,并且每天增长约100,000条记录:

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 ms,经过时间= 2762 ms。

我还考虑过创建一个新表,该表只存储每种货币的最新价格,并且只要新价格进入PriceData表时就会更新。然而,这感觉就像一个肮脏的黑客,我肯定违反了一些数据库规范化原则。

此存储过程由MVC应用程序使用的Web服务层执行,因此执行时间需要更好(我希望将其设置为<100毫秒)。我愿意修改这个表和数据库的架构。

2 个答案:

答案 0 :(得分:2)

您可以尝试将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

您还应该在IdPriceData表的CurrencyPair字段上放置索引。

答案 1 :(得分: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;