2012-01-19 11 views
2

特定の時点では、資産の有効な価格が設定されています。一部の資産は、週に1回、一部は1日に1回の新しい価格です。最新の価格は「実効価格」です。一時的な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の効果的な価格を照会するには

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 

を簡単ですが、それは計算するのに些細な時間を要します。

dbo.AssetPriceへのデータ変更のみが実効価格の再計算を必要とするように、物理的にデータを格納することが理想的です。私は、関連する集約関数はインデックス付きビューでは許可されていないため、インデックス付きビューを作成できないと考えています。

有効な価格(直近の価格)をすばやく検索するためにテーブルを調整するにはどうすればよいですか?

+0

価格を計算するために「些細でない時間がかかる」クエリはどちらですか? –

+0

@ypercube 'AssetId'の有効な価格を見つけるためのクエリは、いくつかの計算ではボトルネックでした - それは彼の答えでRubens Fariasによって書かれたサブクエリと同じようにサブクエリが必要でした。 – Mike

答えて

2

基本的には、2つの異なるアプローチを使用することができます。

  • は間隔を含めるように、テーブルのスキーマを変更します。この場合、有効期限はであることを確認するには、開始日と終了日を保存する必要があります。それで、あなたは単にあなたの希望する価格を得るために簡単な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サーバは特定のキーの重複が想定されていないことを知らないため、カーディナリティ推定値が非常に悪いことに注意してください。 –

関連する問題