2012-01-19 4 views
2

Для данного момента времени актив имеет эффективную цену. Некоторые активы имеют новую цену один раз в неделю, причем один раз в день. Самая последняя цена - «эффективная цена».Как настроить производительность временной таблицы SQL Server

Временная таблица, которая хранит описанные отношения выглядит следующим образом:

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, что требует пересчета эффективной цены. Я считаю, что я не могу создать индексированное представление, потому что соответствующие агрегированные функции не допускаются в индексированном представлении.

Как настроить таблицу, чтобы получить эффективную цену (самую последнюю цену) очень быстро?

+0

Какой запрос принимает «нетривиальное количество времени» для расчета цены? –

+0

@ypercube Запрос, чтобы найти эффективную цену «AssetId», был шеей бутылки в нескольких вычислениях - для этого требовался подзапрос, подобный тому, который был написан Рубенсом Фариасом в его ответе. – Mike

ответ

2

В принципе вы можете использовать два различных подхода:

  • Alter вашу схему таблицы включить интервал. В этом случае вам необходимо сохранить дату начала и окончания, чтобы определить свой эффективный период . При этом вам просто нужно использовать простой 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) 
+0

Обратите внимание, что запросы с 'между startdate и enddate' имеют очень плохие оценки мощности, потому что сервер sql не знает, что не должно быть перекрытий для определенного ключа. –