我有以下'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毫秒)。我愿意修改这个表和数据库的架构。
答案 0 :(得分:2)
您可以尝试将TOP 1
与JOIN
一起使用,并查看它与原始查询的对比情况:
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
您还应该在Id
和PriceData
表的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;