2

質問があります:

var contactInfos = from person in persons

                    join tempDesiredCar in desiredCars on person.contact_id equals tempDesiredCar.groupEntity_id
                                   into tempDesiredCars
                    from desiredCar in tempDesiredCars.DefaultIfEmpty()
                    select new {name = person.name, car = desiredCar.name};

このコードは SQL に変換されます。

SELECT [t1].[name], [t19].[name] AS [car]
FROM [dbo].[Person] AS [t1]
CROSS APPLY ((
        SELECT NULL AS [EMPTY]
        ) AS [t6]
    OUTER APPLY (
        SELECT [t18].[name]
        FROM (
            SELECT [t17].[contact_id], [t17].[name]
            FROM (
                SELECT [t7].[contact_id], [t11].[name]
                FROM [dbo].[DesiredCar] AS [t7]
                INNER JOIN (
                    SELECT MAX([t9].[value]) AS [value]
                    FROM (
                        SELECT [t8].[id] AS [value], [t8].[contact_id]
                        FROM [dbo].[DesiredCar] AS [t8]
                        ) AS [t9]
                    GROUP BY [t9].[contact_id]
                    ) AS [t10] ON ([t7].[id]) = [t10].[value]
                LEFT OUTER JOIN [dbo].[FamilyModel] AS [t11] ON [t11].[id] = [t7].[model]
                WHERE [t7].[model] IS NOT NULL
                UNION
                SELECT [t12].[contact_id], [t16].[name]
                FROM [dbo].[DesiredCar] AS [t12]
                INNER JOIN (
                    SELECT MAX([t14].[value]) AS [value]
                    FROM (
                        SELECT [t13].[id] AS [value], [t13].[contact_id]
                        FROM [dbo].[DesiredCar] AS [t13]
                        ) AS [t14]
                    GROUP BY [t14].[contact_id]
                    ) AS [t15] ON ([t12].[id]) = [t15].[value]
                LEFT OUTER JOIN [dbo].[CarBrand] AS [t16] ON [t16].[id] = [t12].[carBrand_id]
                WHERE [t12].[carBrand_id] IS NOT NULL
                ) AS [t17]
            ) AS [t18]
        where [t1].[contact_id] = [t18].[contact_id]
        ) AS [t19])

そのコードは Apply を使用します。Apply を Left Join に置き換えると、コードの実行速度が数倍速くなります。左結合を使用してLinqにコードを生成させる方法は?

4

3 に答える 3

1

LINQが適用演算子を使用している理由を見つけました。オペランドは、その結合に外部キーからの依存関係があるかどうかをチェックしています。単なるテーブルの場合–linqは「左結合」を使用します。サブクエリにGroupBy、Order Byが含まれ、列が「equals」で使用されている場合、LINQは「Outerapply」を使用します。LINQJOINで単純なサブクエリを使用します。

于 2013-01-11T09:07:42.233 に答える
0

a) join と apply が異なるプランを生成し、b) LINQ が apply を使用している理由がわかりません。これは奇妙なケースです。

回避策を考えてみましたが、うまくいくことを願っています:

//project only the needed columns
var contactInfos = from person in persons
                    join tempDesiredCar in
                         desiredCars.Select(x => new { x.groupEntity_id, x.name })
                         on person.contact_id equals tempDesiredCar.groupEntity_id
                         into tempDesiredCars
                    from desiredCar in tempDesiredCars.DefaultIfEmpty()
                    select new { name = person.name, car = desiredCar.name };

//change join to from
var contactInfos = from person in persons
                   from desiredCar in
                         desiredCars.Select(x => new { x.groupEntity_id, x.name })
                                    .Where(x => person.contact_id = x.groupEntity_id)
                                    .DefaultIfEmpty()
                    select new { name = person.name, car = desiredCar.name };

これらは単なる投機的な書き直しです。偶然にも機能することを願っています...これが問題を解決する良い方法ではないことはわかっていますが、この奇妙なケースでは、これが私が提供できる最善の方法です。

于 2012-12-28T15:47:19.417 に答える
0

クエリプランを調べました。

適用計画は、ネストされたループを使用してテーブルを結合します。Person テーブルのレコードごとに、DesiredCars テーブルのすべてのレコードを読み取ります。データベース内のすべての人の希望する車を本当に見つける必要がありますか? そうでない場合は、最初に Person テーブルを少しフィルタリングすることを検討してください。

結合計画では、ハッシュマッチングを使用してテーブルを結合します。両方のテーブルを 1 回読み取り、1 つのテーブルのマップを作成し、そのマップを 2 番目のテーブルで使用します。オプティマイザは、いくつかのインデックスの推奨事項を指摘しています。これらの推奨事項は、両方の計画に役立つ場合があります。

        <MissingIndexes>
          <MissingIndexGroup Impact="12.6549">
            <MissingIndex Database="[AudiCRM]" Schema="[dbo]" Table="[DesiredCar]">
              <ColumnGroup Usage="INEQUALITY">
                <Column Name="[carBrand_id]" ColumnId="13" />
              </ColumnGroup>
              <ColumnGroup Usage="INCLUDE">
                <Column Name="[id]" ColumnId="1" />
                <Column Name="[contact_id]" ColumnId="2" />
              </ColumnGroup>
            </MissingIndex>
          </MissingIndexGroup>
          <MissingIndexGroup Impact="12.6549">
            <MissingIndex Database="[AudiCRM]" Schema="[dbo]" Table="[DesiredCar]">
              <ColumnGroup Usage="INEQUALITY">
                <Column Name="[model]" ColumnId="3" />
              </ColumnGroup>
              <ColumnGroup Usage="INCLUDE">
                <Column Name="[id]" ColumnId="1" />
                <Column Name="[contact_id]" ColumnId="2" />
              </ColumnGroup>
            </MissingIndex>
          </MissingIndexGroup>
        </MissingIndexes>
于 2012-12-30T04:30:56.380 に答える