1

2つのテーブル(SQL Server 2008)があります:ドキュメントとフィールド。

ドキュメント:

Id  (PK)
Some-Others-Columns 

田畑:

Id  (PK) 
DocumentId  (FK to Documents) 
Name
Value 

すべてのドキュメントには80以上のフィールドが割り当てられています。すべての行がドキュメント+いくつかの特定のフィールド(80以上ではなく、一部のフィールドのみ)であるテーブルを選択する必要があります。

大きなテーブルでは非常に低速で動作するT-SQLコードがありますが、どうすればそれを最適化できますか?

SELECT f1.Value AS 'f1', f2.Value AS 'f2', f3.Value AS 'f3', f4.Value AS 'f4', f5.Value AS 'f5', f6.Value AS 'f6', d.PartyId, d.CreationDate
FROM dbo.Fields AS f WITH (NOLOCK) 
  INNER JOIN dbo.Fields AS f1 ON f.Id = f1.Id 
  INNER JOIN dbo.Documents AS d ON f1.DocumentId = d.Id 
  INNER JOIN dbo.Fields AS f2 ON d.Id = f2.DocumentId
  INNER JOIN dbo.Fields AS f3 ON d.Id = f3.DocumentId
  INNER JOIN dbo.Fields AS f4 ON d.Id = f4.DocumentId
  INNER JOIN dbo.Fields AS f5 ON d.Id = f5.DocumentId
  INNER JOIN dbo.Fields AS f6 ON d.Id = f6.DocumentId

WHERE
    (f1.Name = 'Some-Name-1')
AND (f2.Name = 'Some-Name-2')
AND (f3.Name = 'Some-Name-3')
AND (f4.Name = 'Some-Name-4')
AND (f5.Name = 'Some-Name-5')
AND (f6.Name = 'Some-Name-6')

このクエリを最適化するのを手伝ってください

4

4 に答える 4

2

ピボットのパフォーマンスが向上するかどうかわからない場合は、これをドキュメントに結合して、他のドキュメント フィールドを取得する必要があります。構文が少しずれている可能性があります (修正してほしい場合は、2 つのテーブルとサンプル行を挿入して SQL Fiddle をセットアップできます: http://sqlfiddle.com/ )

SELECT DocumentId, 
[Some-Name-1], [Some-Name-2], [Some-Name-3], [Some-Name-4], [Some-Name-5],[Some-Name-6]
FROM (
  Select f.DocumentId, f.Name, f.Value
  FROM dbo.Fields AS f 
  INNER JOIN dbo.Documents AS d ON f.DocumentId = d.Id ) as SourceTable
PIVOT
(
  SUM(Value)
  FOR Name IN ([Some-Name-1], [Some-Name-2], [Some-Name-3], [Some-Name-4], [Some-Name-5],[Some-Name-6])
) AS PivotTable;
于 2012-11-15T04:29:16.547 に答える
1

ctrl + lを使用して、実行プランと実行に最も時間がかかるものを確認できます。ほとんどの場合、フィールドテーブルのIDと名前、およびドキュメントテーブルのIDのインデックスが必要です。

于 2012-11-15T04:16:56.077 に答える
1

これを試して:

SELECT f1.Value AS 'f1', f2.Value AS 'f2', f3.Value AS 'f3', f4.Value AS 'f4', f5.Value AS 'f5', f6.Value AS 'f6', d.PartyId, d.CreationDate
FROM dbo.Fields AS f WITH (NOLOCK) 
INNER JOIN (SELECT Id, DocumentId, Value FROM dbo.Fields WHERE Name='Some-Name-1') AS f1 
    ON f.Id = f1.Id 
INNER JOIN (SELECT Id, CreationDate, PartyId  FROM dbo.Documents) AS d
    ON f1.DocumentId = d.Id 
INNER JOIN (SELECT Id, DocumentId, Value FROM dbo.Fields WHERE Name='Some-Name-2') AS f2
    ON d.Id = f2.DocumentId
INNER JOIN (SELECT Id, DocumentId, Value FROM dbo.Fields WHERE Name='Some-Name-3') AS f3
    ON d.Id = f3.DocumentId
INNER JOIN (SELECT Id, DocumentId, Value FROM dbo.Fields WHERE Name='Some-Name-4') AS f4
    ON d.Id = f4.DocumentId
INNER JOIN (SELECT Id, DocumentId, Value FROM dbo.Fields WHERE Name='Some-Name-5') AS f5
    ON d.Id = f5.DocumentId
INNER JOIN (SELECT Id, DocumentId, Value FROM dbo.Fields WHERE Name='Some-Name-6') AS f6
    ON d.Id = f6.DocumentId
于 2012-11-15T14:41:32.450 に答える
1

高いパフォーマンス コストは、結合が非常に多いことから生じます。目的のドキュメントの「フィールド」のレコードセットを取得してみませんか? よく分からなかったのかな…

SELECT value 
FROM Documents AS d 
INNER JOIN Fields as f ON d.Id=f.DocumentId 
WHERE (f.Name="Name1" or f.Name="Name2" or.. etc);

ドキュメントのフィールドにすべての「値」列のレコードセットが必要です

列を形成する値が必要な場合は、最初のクエリの後にそれを行う必要があります

于 2012-11-15T04:57:58.373 に答える