今日、アプリケーションの 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
データベース図
データは次のように表示する必要があります。
この設計では、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'