2017-12-23 11 views
-1

VisitとVisitMovementの2つのテーブルが1対多の関係にあります。つまり、1つのVisitには多くのVisitMovement行があります。私はすべての詳細フィールドを取り出してきたが、これらは、テーブル定義です:最新のレコードを1からManyへリレーションシップテーブル

CREATE TABLE [dbo].[Visit] 
(
    [VisitID] [int] IDENTITY(1,1) NOT NULL 
) 

CREATE TABLE [dbo].[VisitMovement](
    [VisitMovementID] [int] IDENTITY(1,1) NOT NULL, 
    [VisitID] [int] NOT NULL 
) 

私が訪問し、最新のVisitMovement行からの詳細情報を返すために必要な多くの時間。

現在、私はこれらの2つのビューを持っていますが、時間が経つにつれてそれは遅くなっています。

たとえば、* vwGetVisitから*を選択した場合、VisitID = 1245の場合、戻すには数秒かかりますが、コストはvwLatestVisitMovementオブジェクトでほとんど上になります。

これを達成するにはどうすればよいでしょうか? VisitID

CREATE VIEW [dbo].[vwGetVisit] as 
     SELECT 
       V.* 
       VM.* 
      FROM 
       Visit V 
      INNER JOIN VisitMovement VM ON 
       V.VisitID = VM.VisitID 
      INNER JOIN vwLatestVisitMovement LVM on 
       VM.VisitMovementID = LVM.VisitMovementID 
      ....many other joins including left joins.... 

CREATE View [dbo].[vwLatestVisitMovement] 
AS 
    SELECT 
     VisitID, 
     max(VisitMovementID) as VisitMovementID 
    FROM 
     dbo.VisitMovement 
    GROUP BY 
     VisitID 
+1

列にVisitMovement' 'テーブルの上にA _single_インデックス' VisitId'昇順、 'VisitMovementId' _descending_べき助けて。これにより、内部結合で一致する行がすぐに見つかるようになり、最初の行が最新のものになります。 (注意:これは、 'VisitMovementId'が意味のある順序を提供することを前提としています。省略した列がある場合(MovementDateなど)、降順の列に置き換えてください。 – HABO

+0

HABOに感謝します。その前はテーブル 'VisitMovement'でした。スキャン数2、論理読み取り1038、今のテーブル 'VisitMovement'。スキャン回数2、論理読み取り526。 – Philip

+0

これは無効です。 LVM.VisitMovementIDに参加してVisitIDを無視します。 – Paparazzi

答えて

1

VisitMovementIDでvWLatestVisitMovementでvisitMovementに参加します。それは私には不思議です... vwLatestVisitMovement .VisitMovementIdはMAXを使用して計算され、このフィールドで多くの費用がかかります。私はより自然にVisitIDで訪問とvwLatestVisitMovementに参加することができると思う、あなたは同じ結果が良いクエリプランを得る必要があります。

VisitMOvementのすべてのデータが必要な場合は、CROSS APPLYまたはROW_NUMBER()OVERを使用できます。

通常、私はROW_NUMBER()を優先します。

これを試してみて、パフォーマンスが優れているかどうかを確認:

CREATE VIEW [dbo].[vwGetVisit] as 
     SELECT 
       V.* 
       , LVM.* 
      FROM 
       Visit V 
      INNER JOIN vwLatestVisitMovement LVM on 
       V.VisitID = LVM.VisitID     
      ....many other joins including left joins.... 

CREATE View [dbo].[vwLatestVisitMovement] 
AS 
    WITH LVM AS (
     -- replace * with fields! 
     SELECT VM.* 
      , ROW_NUMBER() OVER(PARTITION BY VM.VisitID ORDER BY VM.VisitMovementID DESC) AS CheckLastId 
     FROM dbo.VisitMovement AS VM 
    ) 
    SELECT 
     * 
    FROM 
     LVM 
    WHERE CheckLastId = 1 
GO 

appplyクロス付:

CREATE VIEW [dbo].[vwGetVisit] as 
     SELECT 
       V.* 
       , LVM.* 
      FROM 
       Visit V 
      CROSS APPLY (SELECT TOP (1) LM.* FROM dbo.VisitMovement AS LM WHERE LM.VisitID = V.VisitID ORDER BY LM.VisitMovementID DESC) AS LVM 
      ....many other joins including left joins.... 
+0

ありがとうございました。それは理想的であり、より速くヒープしますが、VisitIDのvwLatestVisitMovementとVisitMovementの両方に参加する際の問題は、最新のものだけでなく、すべての行を戻すことです。何か案は? – Philip

+0

今、わかりました、ごめんなさい。私は自分の答えを変えました。 – Ezin82

+0

Ezinありがとうございました。それに関連する奇妙な問題がありますが、別の質問を投稿します。 – Philip

0

インデックスはあなたの問題を解決する必要があります

CREATE UNIQUE CLUSTERED INDEX IDX_vwGetVisit_VisitID 
    ON [vwGetVisit] (VisitID); 
CREATE UNIQUE CLUSTERED INDEX IDX_vwLatestVisit_VisitID 
    ON [vwLastestVisitMovement] (VisitID); 

見解をただし素晴らしいパフォーマンスのために知られていないあなたはパフォーマンスの問題を持っているし続ける場合は、必要に応じてクエリを繰り返したほうが良いかもしれ。

+0

ありがとうございますが、すでにテーブルにインデックスがあります。 – Philip

+0

@Philipテーブルまたはビューで? – SomeGuy

+0

申し訳ありませんが、表示されていません。ただし、互換性はありません。 - ビュー "vwGetVisit"に索引を作成できません。LEFT、RIGHT、またはFULL OUTER結合を使用し、索引付きビューではOUTER結合は使用できないためです。代わりにINNER結合を使用することを検討してください。 私はそれが関連しているとは思わなかったので、申し訳ありませんが、ビューから結合のヒープ全体を切断します。私はそれをお詫び申し上げます。 – Philip

関連する問題