【问题标题】:How to tune performance of a temporal SQL Server table如何调整时态 SQL Server 表的性能
【发布时间】:2012-01-19 00:31:31
【问题描述】:

对于给定的时间点,资产具有有效价格。有些资产每周有一次新价格,有些则每天一次。最近的价格是“有效价格”。

存储所描述关系的时态表如下所示:

CREATE TABLE dbo.AssetPrice
(
    AssetId int NOT NULL -- FK to the table dbo.Asset
    ,EffectiveDate datetime NOT NULL
    ,Price decimal NOT NULL
    CONSTRAINT PK_AssetPrice PRIMARY KEY CLUSTERED (AssetId,EffectiveDate,Price)
)

数据看起来像这样:

AssetId    EffectiveDate    Price
-------    -------------    -----
      1       2012-01-11     1.21
      1       2012-01-12     1.22
      2       2012-01-11     3.55
      2       2012-01-12     3.60
      3       2012-01-04     5.15
      3       2012-01-11     5.14

查询AssetId 的有效价格很简单,但计算起来却非常耗时。

以物理方式存储数据是理想的,因此只有数据更改为dbo.AssetPrice 需要重新计算有效价格。我相信我无法创建索引视图,因为索引视图中不允许使用相关的聚合函数。

如何调整表格以快速检索有效价格(最新价格)?

【问题讨论】:

  • 哪个查询需要“非常长的时间”来计算价格?
  • @ypercube 查找AssetId 的有效价格的查询是一些计算的瓶颈——它需要一个子查询,就像鲁本斯·法里亚斯在他的回答中写的那样。

标签: sql-server sql-server-2008 indexing temporal-database


【解决方案1】:

基本上你可以使用两种不同的方法:

  • 更改表架构以包含间隔。在这种情况下,您需要存储开始和结束日期以确定您的有效期间。有了这个,您只需要使用一个简单的 BETWEEN 即可获得您想要的价格。您还可以在开始和结束日期以及 AssetId 上添加非聚集索引以获得最佳性能。默认情况下,您可以将结束日期添加为“9999-12-31”,并且每次资产有新价格时,您都会结束当前周期并开始新的周期。我(个人)更喜欢这个选项。

  • 坚持使用此架构并在 EffectiveDate 和 AssetId 上创建非聚集索引。您需要构建一个子选择以获取生效日期小于您所需日期的资产的最大日期,如下所示:

.

CREATE INDEX    IX_AssetPrice_EffectiveDate
                ON AssetPrice (EffectiveDate, AssetId) INCLUDE (Price)
DECLARE @AssetId int = NULL, @EffectiveDate datetime = '2012-01-11'
SELECT  AssetPrice.AssetId, AssetPrice.Price, AssetPrice.EffectiveDate
FROM    AssetPrice
JOIN    (
            SELECT  AssetId, MAX(EffectiveDate) EffectiveDate
            FROM    AssetPrice
            WHERE   EffectiveDate <= @EffectiveDate AND
                    (AssetId = @AssetId OR @AssetId IS NULL)
            GROUP BY AssetId
        ) Effective
        ON  AssetPrice.AssetId = Effective.AssetId AND
            AssetPrice.EffectiveDate = Effective.EffectiveDate
WHERE   (AssetPrice.AssetId = @AssetId OR @AssetId IS NULL)

【讨论】:

  • 请注意,使用 between startdate and enddate 的查询具有非常糟糕的基数估计,因为 sql server 不知道某个键不应该有重叠。
猜你喜欢
  • 2015-07-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-03-03
  • 2011-03-17
  • 1970-01-01
相关资源
最近更新 更多