現在、いくつかのテーブルからデータを取得するために作成したビューを使用しています。これに関する主な要因は、CTEと文字列を組み合わせて複数の行を1つの列に組み合わせる(複数回)ことで仕様を把握することです。ビューは機能しているが、ユーザーは最近、それが遅すぎると不満を述べている。
現在、ビューのセットアップは次のようになります。
;
With thing1 AS
(
SELECT DISTINCT
/* huge block of code with joins and such
that gets the individual fields and concatenates
personnel names to one row */
)
,
thing2 AS
(
SELECT TaskName,
Company,
Lease,
TaskBegin,
TaskEnd,
Field,
Personnel,
Invoice,
InvDate,
InvTot,
ROW_NUMBER() OVER (Partition by TaskName ORDER BY [TaskName] ASC) rn
FROM thing1
)
SELECT TaskName,
Company,
Lease,
Field,
ISNULL(Personnel, '') as 'Personnel',
TaskBegin,
TaskEnd,
ISNULL (STUFF( (SELECT ', ' + Invoice
FROM thing1
WHERE (thing1.TaskName = thing2.TaskName)
AND thing2.rn = 1
ORDER BY Invoice
FOR XML PATH('')), 1, 1, ''), '') AS 'Invoice',
ISNULL (STUFF( (SELECT ', ' + InvDate
FROM thing1
WHERE (thing1.TaskName = thing2.TaskName)
AND thing2.rn = 1
ORDER BY Invoice
FOR XML PATH('')), 1, 1, ''), '') AS 'InvoiceDate',
ISNULL (STUFF( (SELECT ', ' + InvTot
FROM thing1
WHERE (thing1.TaskName = thing2.TaskName)
AND thing2.rn = 1
ORDER BY Invoice
FOR XML PATH('')), 1, 1, ''), '') AS 'InvoiceTotal'
FROM thing2 WHERE rn = 1
GO
したがって、意図したとおりに機能します。問題は、Invoice、InvDate、およびInvTotを連結する最後のSELECTに到達すると、クエリが1秒を必要としないこと(つまり、thing2からの単純なSELECT)から、コースの実行に最大7秒かかることです。 (平均時間は約5秒です。)責任の一部は増え続けるデータベースにあると私はかなり確信しています。このビューは、レコードがはるかに少ないテスト環境ではるかに速くロードされます。
私の質問はこうです:DBでより速く、リソースをあまり消費しない方法でこれに対処することは可能ですか?
コードの問題は、CTEへの複数のアクセスとそこにあるすべての複雑なロジックにあるようです。 UNPIVOT/PIVOTを使用して、すべてを1つのパスで実行する必要があります。私はここで同様のことをしました: http://spaghettidba.com/2011/10/13/concatenating-multiple-columns-across-rows/
私の例では、異なる言語の文の連結が見つかりますが(正確には何をしているのかではありません)、同じテクニックを使用できるように思えます。
あなたが持っているものは、レポートのために転置する必要があるEAVパターン(コードのブロックがほとんど同じテイクへの結合である)のようです。その場合、PIVOT
機能を使用すると、CTEをより効率的にすることができます(コードの可読性と実行時の両方で)。 http://technet.Microsoft.com/en- us/library/ms177410(v = sql.105).aspx
あなたがそれを信じているならFOR XML PATH
はビューを遅くする原因です。別のアプローチを使用して、行を単一の列に連結できます。この SQL Fiddle は、連結に再帰CTEを使用する方法を示しています。
Thing1とThing2の間にcte1、cte2、cte2、cte4を挿入し、最後の3つの列(FOR XML PATHを使用する場所)の代わりにcte4のInvoice、Invdate、InvTot列を直接使用するだけです。