4

50,000 個の製品 ID のメモリ内にリストリストがあります。これらすべての製品を DB から取得したいと考えています。UsingdbContext.Products.Where(p => list.contains(p.ID))は SQL で巨大な IN を生成します - WHERE ID IN (2134,1324543,5675,32451,45735...)、そしてそれは永遠にかかります。これは、SQL Server がこのような大きな文字列を解析するのに時間がかかることと、実行計画が適切でないことが一因です。(代わりに一時テーブルを使用しようとすることでこれを知っています)。

そこで、SQLBulkCopy を使用して ID を一時テーブルに挿入し、実行しました。

dbContext.Set<Product>().SqlQuery("SELECT * FROM Products WHERE ID IN (SELECT ID FROM #tmp))"

これにより、良好なパフォーマンスが得られました。ただし、今は製品とそのサプライヤー (製品ごとに複数) が必要です。カスタム SQL コマンドを使用しても、私が知っている複雑なオブジェクトを取得する方法はありません。では、一時テーブルを使用して、サプライヤーと一緒に製品を取得するにはどうすればよいでしょうか?

(何らかの方法で LINQ で一時テーブルを参照できれば、それで問題ありませんdbContext.Products.Where(p => dbContext.TempTable.Any(t => t.ID==p.ID))。できるのは . UDF でそれを参照できれば、それも良いことですが、できません。実際のテーブルは使用できません。同時ユーザーが一貫性のない状態のままになるためです。)

ありがとう

4

2 に答える 2

3

Joinではなく、構文を使用して生成された sql を調査することに興味がありましたContains。これが私のテストのコードです:

IQueryable<Product> queryable = Uow.ProductRepository.All;
List<int> inMemKeys = new int[] { 2134, 1324543, 5675, 32451, 45735 }.ToList();
string sql1 = queryable.Where(p => inMemKeys.Contains(p.ID)).ToString();

string sql2 = queryable.Join(inMemKeys, t => t.ID, pk => pk, (t, pk) => t).ToString();

これは、Contains (sql1) を使用して生成された sql です。

SELECT
    [extent1].[id] AS [id],...etc
FROM [dbo].[products] AS [extent1]
WHERE ([extent1].[id] IN (2134, 1324543, 5675, 32451, 45735))

これは、結合を使用して生成された sql です。

SELECT
    [extent1].[id] AS [id],...etc
FROM [dbo].[products] AS [extent1]
    INNER JOIN (SELECT
        [unionall3].[c1] AS [c1]
    FROM (SELECT
        [unionall2].[c1] AS [c1]
    FROM (SELECT
        [unionall1].[c1] AS [c1]
    FROM (SELECT
        2134 AS [c1]
    FROM (SELECT
        1 AS x) AS [singlerowtable1] UNION ALL SELECT
        1324543 AS [c1]
    FROM (SELECT
        1 AS x) AS [singlerowtable2]) AS [unionall1] UNION ALL SELECT
        5675 AS [c1]
    FROM (SELECT
        1 AS x) AS [singlerowtable3]) AS [unionall2] UNION ALL SELECT
        32451 AS [c1]
    FROM (SELECT
        1 AS x) AS [singlerowtable4]) AS [unionall3] UNION ALL SELECT
        45735 AS [c1]
    FROM (SELECT
        1 AS x) AS [singlerowtable5]) AS [unionall4]
        ON [extent1].[id] = [unionall4].[c1]

そのため、SQL は、union all を使用して大きな select ステートメントを作成し、一時テーブルに相当するものを作成してから、そのテーブルに結合します。SQLはより冗長ですが、効率的である可能性があります-残念ながら、私は言う資格がありません.

見出しに記載されている質問には答えませんが、巨人を回避する方法を示していINます。わかりました....今は巨大UNION ALLです....とにかく...この貢献が誰かに役立つことを願っています

于 2013-10-21T09:56:51.483 に答える