0

今日、アプリケーションの DB 設計とパフォーマンスの問題に関して、次の質問をしました。

重いテーブルからの DB 設計とデータ取得

しかし、それについては多くの回答を得ることができませんでした。わかりません。質問を適切に説明していない可能性があります。ここで、専門家からの提案を期待して、質問を再定義しました。

特定のテーブルからデータを選択しているときに、パフォーマンスの問題に直面しています。アプリケーションのビジネス ロジックは次のとおりです。多数のインポート プロセスがあり、その結果、親列名の下にピボット列が作成され、ユーザーに表示されます。列がピボットされると、システムが行を列に変換するのに時間がかかり、パフォーマンスが低下します。この機能に関連するデータベース テーブルは次のとおりです。 N 個のクライアントが存在する可能性があります。CLT_Clients テーブルには、クライアント情報が格納されます。

クライアントには N 個のプロジェクトを関連付けることができます。PRJ_Projects テーブルには、プロジェクト情報とクライアントへのリンクが格納されます。

プロジェクトに関連付けられた N 個のリストが存在する可能性があります。PRJ_Listings テーブルには、リスト情報とプロジェクトへのリンクが格納されます。

リストに関連付けられた N 個のソース エンティティが存在する可能性があります。ST_Entities テーブルには、ソース エンティティ情報とリストへのリンクが格納されます。

このソース エンティティは、InvestorID、ポジション値、ソース日付、アクティブおよび式のステータスを含む実際のインポートです。

The name of the import e.g. L1Entity1 is stored in ST_Entities table alongwith ID field i.e. EntityID
InvestorID, Position, Source Date, Active and Formula values get stored in ST_Positions table 

データベース図 DB設計

データは次のように表示する必要があります。 データ ビュー

この設計では、Position、Source Date、IsActive、Formula 列がピボットされるため、N 個のインポートを処理できます。

この設計で私が直面している問題は、10 ~ 12 を超えるソース エンティティのデータを選択する必要があり、約 150 のソース エンティティを表示する必要がある場合、システムのパフォーマンスが非常に遅くなることです。データは行ごとに保存されず、列ごとに表示する必要があるため、これらの列をピボットするために動的クエリが作成され、時間がかかります。

質問 1:現在のデータベース設計が正しいか、新しい設計で変更する必要がある場合は、Position、Source Date、IsActive、Formula のそれぞれに 150 列を使用して、コメントまたは提案してください。この新しい方法では、データは取得する必要がある方法で既に保存されています。つまり、データをピボット/アンピボットする必要はありません。しかし、欠点は次のとおりです。

a) このテーブルには 600 を超える列がありますか?

b) ソース エンティティには 150 という制限があります。

質問 2:現在の状態を維持する必要がある場合、パフォーマンスを向上させるために何ができますか?

以下のインデックス作成と Pivot メソッドの情報を参照してください。

ポジション テーブルのインデックスについては、データが ProjectID または EntityID に基づいてポジション テーブルから選択されるため、クラスタ化インデックスを使用して ProjectID フィールドも取得しました。

EntityID を使用して Position テーブルからデータを選択する場合は常に、JOIN で使用されます。また、ProjectID を使用してこのテーブルからデータを選択する場合は常に、WHERE で使用されます。

ここで注意すべき点は、ProjectID にクラスター化されたインデックスがありますが、ピボットされた列または EntityID にインデックスを作成していないことです。ここに改善の余地はありますか?

使用されるピボット方法:

Example 1:

'Select * From
(
    Select DD.InvestorID,Cast(1 As Bit) As IsDSInvestor,DD.Position,
    Case DD.ProjectID
    When ' + CAST(@ProjectID AS VARCHAR) +' Then DE.SourceName 
    Else ''' + @PPDeliveryDate + '''+DE.SourceName
    End As SourceName
    From DE_PositionData DD
    Inner Join DE_DataEntities DE ON DE.EntityID=DD.EntityID
    Where DD.ProjectID IN (' + CAST(@ProjectID AS VARCHAR) +',' + CAST(@PreviousProjectID AS VARCHAR) +') AND InvestorID IS NOT NULL

) IDD
Pivot
(
    max(Position) for SourceName in ('+ @DataColumns+')
) as p1'

例 2:

'Select * From
    (
        Select DD.InvestorID As DSSOFID,Cast(1 As Bit) As IsActiveInvestor,
        Case ST.SourceTypeCode
            When ''RSH'' Then Cast(IsNull(DD.IsActive,0) As Int)
            Else Cast(IsNull(DD.IsActive,1) As Int) 
        End As IsActive,
        ''~''+DE.SourceName As ActiveSourceName
        From DE_DataEntities DE
        Left Join DE_PositionData DD ON DE.EntityID=DD.EntityID
        Left Join 
        (
            Select * From #DataSources
            Where ProjectID=' + CAST(@ProjectID AS VARCHAR) +'
        ) ST ON ST.ESourceID=DE.ESourceID
        Where DE.ProjectID=' + CAST(@ProjectID AS VARCHAR) +' AND ST.SourceTypeCode NOT IN (''PBC'',''EBL'',''REG'')
        AND InvestorID IS NOT NULL

    ) IDD
    Pivot
    (
        Max(IsActive) for ActiveSourceName in ('+ @DataColumns+')
    ) As p1'
4

1 に答える 1

2

私は次のことを提案します。

データを正規化された形式で保存する必要があります。インデックスを設定して、データのピボットを高速化できるはずです。ピボットに使用している実際のクエリを投稿していただければ、お役に立てるかもしれません。

この方法でデータを保存する理由は多数あります。

  • 繰り返しブロック数の柔軟性
  • 多くのデータベースでは、列数またはテーブルの合計幅に制限があります。設計がこれらの制限に近づくことは望ましくありません。
  • 各ブロックに関する追加情報が必要な場合があります。テーブルには常に CreatedBy 列と CreatedAt 列を含めますが、これはブロックごとに行う必要があります。
  • 要約の柔軟性が高まります。
  • 中間値の追加/削除は面倒です。

とはいえ、ピボット テーブルには重要な利点が 1 つあります。それは、ユーザーが見たいものです。データが 1 日に 1 回だけ更新される場合は、ピボットを含むレポート テーブルを作成する必要があります。

データが 1 日を通して増分的に更新される場合は、トリガー (またはストアド プロシージャ コード) を設定して、ベース テーブルとレポートの概要を更新できます。

しかし、先に述べたように、別の質問をする必要があります。それは、ピボットに使用している特定の方法です。おそらく、そこでパフォーマンスを向上させることができます。

于 2012-06-01T23:22:56.177 に答える