0

ASP.NET 4.5、Entity Framework 5.0、LINQ を SQL Server 2012 で使用しています。

これは、不動産 Web サイト用の Web ベースのアプリケーションです。このクエリがデータを取得しているテーブルには、約 200 列と約 320 万行があります。

EF を使用してデータを取得すると、次のクエリが生成されます。

SELECT TOP (2) 
[Filter1].[ListingID] AS [ListingID], 
[Filter1].[Address] AS [Address], 
[Filter1].[Beds] AS [Beds], 
[Filter1].[BathsFull] AS [BathsFull], 
[Filter1].[ListPrice] AS [ListPrice], 
[Filter1].[RemarksPublic] AS [RemarksPublic], 
[Filter1].[MLSBoardID] AS [MLSBoardID], 
[Filter1].[PropertyTypeID] AS [PropertyTypeID], 
[Filter1].[sysid] AS [sysid], 
[Filter1].[ListAgentID] AS [ListAgentID], 
[Filter1].[LastUpdateDate] AS [LastUpdateDate], 
[Filter1].[ShowAddressOnlineYN] AS [ShowAddressOnlineYN], 
[Filter1].[City] AS [City], 
[Filter1].[State] AS [State], 
[Filter1].[ZipCode] AS [ZipCode], 
[Filter1].[MLSNumber] AS [MLSNumber], 
[Filter1].[County] AS [County], 
[Filter1].[LeasePrice] AS [LeasePrice]
FROM ( SELECT [Extent1].[ListingID] AS [ListingID], [Extent1].[MLSBoardID] AS [MLSBoardID], [Extent1].[PropertyTypeID] AS [PropertyTypeID], [Extent1].[sysid] AS [sysid], [Extent1].[Address] AS [Address], [Extent1].[BathsFull] AS [BathsFull], [Extent1].[Beds] AS [Beds], [Extent1].[City] AS [City], [Extent1].[County] AS [County], [Extent1].[LastUpdateDate] AS [LastUpdateDate], [Extent1].[LeasePrice] AS [LeasePrice], [Extent1].[ListAgentID] AS [ListAgentID], [Extent1].[ListPrice] AS [ListPrice], [Extent1].[MLSNumber] AS [MLSNumber], [Extent1].[RemarksPublic] AS [RemarksPublic], [Extent1].[ShowAddressOnlineYN] AS [ShowAddressOnlineYN], [Extent1].[State] AS [State], [Extent1].[ZipCode] AS [ZipCode], row_number() OVER (ORDER BY (Case When [Extent1].[ListAgentID] IN ('##########') Then 0 Else 1 End), ListPrice DESC, LeasePrice DESC) AS [row_number]
    FROM [dbo].[Listings] AS [Extent1]
    WHERE 1009 = [Extent1].[PropertyTypeID]
)  AS [Filter1]
WHERE [Filter1].[row_number] > 0
ORDER BY (Case When [Filter1].[ListAgentID] IN ('##########') Then 0 Else 1 End), ListPrice DESC, LeasePrice DESC

このクエリを実行して 2 行を返すには、推定 45 ~ 50 秒かかります。実行計画からわかるように、コストの大部分は「並べ替え」と「並べ替え (上位 N 並べ替え)」にあります。これらは、クエリ全体の 79% のコストを占めています。

上記のクエリを次のように手動で書き直します。

SELECT TOP (2) 
[ListingID], 
[Address], 
[Beds], 
[BathsFull], 
[ListPrice], 
[RemarksPublic], 
[MLSBoardID], 
[PropertyTypeID], 
[sysid], 
[ListAgentID], 
[LastUpdateDate], 
[ShowAddressOnlineYN], 
[City], 
[State], 
[ZipCode], 
[MLSNumber], 
[County], 
[LeasePrice]
FROM  dbo.Listings
WHERE 1009 = [PropertyTypeID]
ORDER BY (Case When [ListAgentID] IN ('##########') Then 0 Else 1 End), ListPrice DESC, LeasePrice DESC

私のクエリは前のクエリとまったく同じ結果を返しますが、実行にかかる時間は 1 秒未満です (「並べ替え (上位 N 並べ替え)」に 91% のコストがかかります)。どちらのクエリも、実行プランの「インデックス シーク」で同じインデックスを使用します。

最初のクエリをより速く実行するにはどうすればよいですか? インデックスを使ってあらゆる種類のことを試しましたが、私が書いた 2 番目のクエリの速度で実行できないようです。

ありとあらゆる助けをいただければ幸いです。詳細が必要な場合は、お知らせください。

4

1 に答える 1

1

コメントありがとうございます。

@Rowland - LINQ クエリは完全に動的であり、クエリがいくつかの要因によって生成される非常に複雑なシステムに統合されているため、表示するのは困難です。

@meda - はい、フィールドの 1 つとしてフィールド「PropertyTypeID」を持つインデックスがあります。問題はありますか?

@Martin - その通りです。

この問題は、order by の生成方法に関係していました。私はそのメソッドを微調整しました。これは、LINQ to EF が同じ結果を取得するために生成した結果の SQL クエリです。

SELECT TOP (2) 
[Project1].[ListingID] AS [ListingID], 
[Project1].[Address] AS [Address], 
[Project1].[Beds] AS [Beds], 
[Project1].[BathsFull] AS [BathsFull], 
[Project1].[ListPrice] AS [ListPrice], 
[Project1].[RemarksPublic] AS [RemarksPublic], 
[Project1].[MLSBoardID] AS [MLSBoardID], 
[Project1].[PropertyTypeID] AS [PropertyTypeID], 
[Project1].[sysid] AS [sysid], 
[Project1].[ListAgentID] AS [ListAgentID], 
[Project1].[LastUpdateDate] AS [LastUpdateDate], 
[Project1].[ShowAddressOnlineYN] AS [ShowAddressOnlineYN], 
[Project1].[City] AS [City], 
[Project1].[State] AS [State], 
[Project1].[ZipCode] AS [ZipCode], 
[Project1].[MLSNumber] AS [MLSNumber], 
[Project1].[County] AS [County], 
[Project1].[LeasePrice] AS [LeasePrice]
FROM ( SELECT 
    CASE WHEN ([Extent1].[ListAgentID] IN ('XXXXXXXXX')) THEN 0 ELSE 1 END AS [C1], 
    [Extent1].[ListingID] AS [ListingID], 
    [Extent1].[MLSBoardID] AS [MLSBoardID], 
    [Extent1].[PropertyTypeID] AS [PropertyTypeID], 
    [Extent1].[sysid] AS [sysid], 
    [Extent1].[Address] AS [Address], 
    [Extent1].[BathsFull] AS [BathsFull], 
    [Extent1].[Beds] AS [Beds], 
    [Extent1].[City] AS [City], 
    [Extent1].[County] AS [County], 
    [Extent1].[LastUpdateDate] AS [LastUpdateDate], 
    [Extent1].[LeasePrice] AS [LeasePrice], 
    [Extent1].[ListAgentID] AS [ListAgentID], 
    [Extent1].[ListPrice] AS [ListPrice], 
    [Extent1].[MLSNumber] AS [MLSNumber], 
    [Extent1].[RemarksPublic] AS [RemarksPublic], 
    [Extent1].[ShowAddressOnlineYN] AS [ShowAddressOnlineYN], 
    [Extent1].[State] AS [State], 
    [Extent1].[ZipCode] AS [ZipCode]
    FROM [dbo].[Listings] AS [Extent1]
    WHERE 1009 = [Extent1].[PropertyTypeID]
)  AS [Project1]
ORDER BY [Project1].[C1] ASC, [Project1].[ListPrice] DESC, [Project1].[LeasePrice] DESC

これは、実行するのに 1 秒もかかりません。ご意見をお寄せいただきありがとうございます。

于 2013-07-30T12:27:35.980 に答える