2016-10-21 13 views
1

I次の2つの表があります。SQL Serverの:WHERE句内に複数のCTEとサブクエリを持つクエリのパフォーマンスを向上させる方法

CREATE TABLE Portfolio.DailyStats 
    (
    Date date NOT NULL Primary Key, 
    NAV int NOT NULL, 
    SP500 decimal(8,4) NULL, 
    R2K decimal(8,4) NULL, 
    NetExp decimal(8,4) NULL, 
    GrossExp decimal(8,4) NULL, 
    ) 
    GO 
    ALTER TABLE Portfolio.DailyStats 
    ADD [YrMn] as CONVERT(varchar(7), Date) 
    GO 

80間:ここ

CREATE TABLE Portfolio.DailyPortfolio 
    (
    BbgID varchar(30) NOT NULL, 
    Ticker varchar(22) NULL, 
    Cusip char(9) NULL, 
    SecurityDescription varchar(50) NOT NULL, 
    AssetCategory varchar(25) NOT NULL, 
    LSPosition char(3) NULL, 
    Ccy varchar(25) NOT NULL, 
    Quantity int NULL, 
    AvgCost decimal(7,3) NULL, 
    PriceLocal decimal(7,3) NULL, 
    Cost int NULL, 
    MktValNet int NULL, 
    GLPeriod int NULL, 
    Beta decimal(4,2) NULL, 
    BetaExpNet int NULL, 
    BetaExpGross int NULL, 
    Delta decimal(4,2) NULL, 
    DeltaExpNet int NULL, 
    DeltaExpGross int NULL, 
    Issuer varchar(48) NOT NULL, 
    Country varchar(30) NOT NULL, 
    Region varchar(20) NOT NULL, 
    Sector varchar(30) NOT NULL, 
    Industry varchar(48) NOT NULL, 
    MktCapCategory varchar(24) NULL, 
    MktCapEnd int NULL, 
    Date date NOT NULL, 
    PortfolioID AS BbgID+LSPosition+ Convert(varchar(8),Date,112) Persisted Primary Key 
    ) 
    GO 

が第二のテーブルです毎日DailyPortfolioテーブルに-100行が追加されます(テーブルには現在約32,000行あります)。 DailyStatsテーブルに1営業日ごとに1行が追加されます(現在約500行あります)。 Daily PortfolioテーブルのDate列には、DailyStatsテーブルのDate列とのForeign Key関係があります。

最後の四半期を日付範囲として使用して、両方のテーブルのいくつかの列を含むビューを作成する必要がありました。このビューの最後の列は、四半期の3ヶ月のそれぞれの最初の日付にNAVを使用して平均が計算される、計算のNAV列の平均を使用します。ビューのDDLは次のとおりです。

CREATE VIEW Portfolio.PNLLastQTD 
    AS 
    WITH CTE1 
    AS 
    (
    Select Date, NAV,YrMn, ROW_NUMBER() OVER (PARTITION BY YrMn ORDER BY Date) AS Row 
    FROM Portfolio.DailyStats 

    WHERE DATE BETWEEN 
     (SELECT Convert(date, DATEADD(q, DATEDIFF(q,0,GETDATE()) -1 ,0))) 
    AND 
     (SELECT Convert(date, DATEADD(s,-1,DATEADD(q, DATEDIFF(q,0,GETDATE()),0)))) 
    ), 
    CTE2 
    AS 
    ( 
    SELECT AvG (NAV) As AvgNAV 
    FROM CTE1 
    WHERE Row=1 
    ) 
    SELECT IssuerLS, Issuer, Ticker, SUM (GLPeriod) As [PNL], 
     CAST(SUM(GLPeriod)As Decimal (13,2))/CAST(CTE2.[AvgNAV] As Decimal (13,2)) as [%ofNAV] 
    FROM Portfolio.DailyPortfolioIssuerLS ls 
    JOIN cte2 on 1=1 
    WHERE ReportDate 
    BETWEEN 
     (SELECT Convert(date, DATEADD(q, DATEDIFF(q,0,GETDATE()) -1 ,0))) 
    AND 
     (SELECT Convert(date, DATEADD(s,-1,DATEADD(q, DATEDIFF(q,0,GETDATE()),0)))) 
    GROUP BY 
     Issuer, Ticker, IssuerLS, CTE2.[AvgNAV] 
    GO 

ビューは正常に動作しますが、実行には約20秒かかります。私はここにいくつかの質問があります:

  1. ビューのDDLにいくつかの変更が加えられますか?
  2. DailyPortfolioテーブルの(可能な場合)日付列に非クラスタ化インデックスを作成することをお勧めしますか?
  3. この特定の問題のクエリパフォーマンスを向上させるために何か考えておくべきことはありますか?

ありがとうございました。私がSQLに慣れてきたので、あからさまな間違いを許してください。

+1

この記事はdba.stackexchange.comとcodereview.stackexchange.comに投稿していますが、役に立つ回答もあります。 – scsimon

+1

クエリに含まれるテーブルに適切なインデックスを付けることで、パフォーマンスが向上する可能性があります。 SSMSで実行計画を分析すると、おそらくいくつか提案されます。 –

答えて

1

私はこの質問のループをクローズしたかったのです。私がここで必要だったのは、2つの非クラスタ化インデックスを作成することでした。私は次の手順を使用しました:

  1. クエリウィンドウに自分のクエリを配置しました。
  2. 私のツールボックスの "見積もり実行計画を表示"ボタンをクリックすると、非クラスタインデックスが見つからないことがすぐに分かりました。

    USE [OurDB] 
    GO 
    CREATE NONCLUSTERED INDEX NCI_DailyPort_Issuer_Date 
    ON [Portfolio].[DailyPortfolio] ([Issuer],[Date]) 
    GO 
    
  3. 繰り返しステップ2と推奨されているように第二の非クラスタ化インデックスを作成しました::

    USE [OurDB] 
    GO 
    CREATE NONCLUSTERED INDEX NCI_DailyPort_Date_INC_DexpN_Issuer 
    ON [Portfolio].[DailyPortfolio] ([Date]) 
    INCLUDE ([DeltaExpNet],[Issuer]) 
    GO  
    

クエリが今よりも少ないを取る最初の非クラスタ化インデックスを作成し

  • 実行するのに3秒かかり、それ以前の24秒よりもはるかに優れています。

    注:欠落しているインデックスについて通知する行を右クリックすると、時間を節約するインデックスのコードを表示するオプションを選択できます。

  • 関連する問題