Linq2SqlをORMとして使用していて、次の問題が発生しています。2つのテーブルがあり、それらをclient(id、name)およびclient_action(id、clientid、date)と呼びます。'client'テーブルにはクライアントが含まれ、client_actionにはユーザーのアクションのログが含まれ、最初に必要なものがあります。
linq2sqlクエリ(ページングと並べ替えを使用)があり、その結果、次のSQLが生成されました。
SELECT TOP (10) /* columns here */
FROM (
SELECT /* columns here */
FROM [dbo].[client] AS [t0]
CROSS APPLY ((
SELECT NULL AS [EMPTY]
) AS [t8]
OUTER APPLY (
SELECT [t9].[source]
FROM [action] AS [t9]
INNER JOIN (
SELECT MIN([t10].[actionID]) AS [value], [t10].[ClientID]
FROM [client_action] AS [t10]
GROUP BY [t10].[clientID]
) AS [t11] ON [t9].[ID] = [t11].[value]
WHERE [t0].[ID] = [t11].[ClientID]
) AS [t12])
) AS [t17]
WHERE /* filter for fields from the client table */
ORDER BY [t17].[date_created] DESC
そのクエリに論理エラーがあり、私はそれを変更しました。これで、生成されたSQLは次のようになります。
SELECT TOP (10) /* columns here */
FROM (
SELECT /* columns here */
FROM (
SELECT /* columns here */
FROM [dbo].[client] AS [t0]
CROSS APPLY ((
SELECT NULL AS [EMPTY]
) AS [t3]
OUTER APPLY (
SELECT [t7].[value]
FROM (
SELECT [t5].[ClientID], (
SELECT TOP (1) [t6].[ID]
FROM [client_action] AS [t6]
WHERE [t5].[clientID] = [t6].[clientID]
ORDER BY [t6].[date_created]
) AS [value]
FROM (
SELECT [t4].[clientID]
FROM [client_action] AS [t4]
GROUP BY [t4].[clientID]
) AS [t5]
) AS [t7]
WHERE [t0].[ID] = [t7].[clientID]
) AS [t8])
LEFT OUTER JOIN [client_action] AS [t9] ON [t8].[value] = [t9].[ID]
) AS [t26]
) AS [t27]
WHERE /* filter for fields from client table */
ORDER BY [t27].[date_created] DESC
そして、パフォーマンスの問題が発生します。'SET STATISTICS IO ON'を使用して両方のクエリを実行したところ、興味深い結果が得られました。
- 最初のクエリの場合:
- クライアントテーブルはフィルタリングされます
- 「トップ10」が適用されました
- 結果の10レコードに「クロスアプライ」が適用されます
- 2番目のクエリの場合:
- クライアントテーブルがフィルタリングされます(約10,000レコードが見つかりました)
- その10Kレコードに適用される「クロスアプライ」
- 「トップ10」が適用されました
そのため、2番目のクエリの動作が大幅に遅くなります。可能な場合はいつでもフィルタリング後に「クロスアプライ」が適用されるようにクエリを「微調整」する方法はありますか?
問題は、2つのクロスアプライがあり、そこにさらに2つの結合があり、すべてが非常に遅くなることです。クエリの速度を向上させることができるインデックスを作成しましたが、それでも煩わしいほど遅いです。
ヘルプヘルプ ヘルプ。