0

特定のプロパティの最大値を持つオブジェクトを返すために、どのクエリがより優れたパフォーマンスを発揮しますか?

 var i = from item in listOfItems
         orderby item.Number descending
         select item;

また:

 var i = from item in listOfItems
          where item.Number== (from l in listOfItems select item).Max(l => l.Number)
          select item;
4

2 に答える 2

1

SQL では、2 つのクエリは次のように変換されます (少なくとも、必要なオブジェクトを選択するために結果の IEnumerables で .FirstOrDefault() を実行する場合):

SELECT TOP (1) [t0].[Number]
FROM [Item] AS [t0]
ORDER BY [t0].[Number] DESC

SELECT TOP (1) [t0].[Number]
FROM [Item] AS [t0]
WHERE [t0].[Number] = ((
    SELECT MAX([t1].[Number])
    FROM [Item] AS [t1]
    ))

事実に基づいてどちらが速いかはわかりませんが、最初のオーダーバイソリューションを使用します.

-* データベースのクエリに対応するように編集 *-

メモリ内コレクションをクエリしている場合、違いは非常に小さいはずです。

ただし、以下は、100.000 個の半乱数を 2 つの異なるクエリ方法でそれぞれ 10 回クエリすることによる、まったく非科学的なテストの結果です。

By desc (0): 00:00:00.0173879
By .Max (0): 00:00:00.0132833

By desc (1): 00:00:00.0250781
By .Max (1): 00:00:00.0140374

By desc (2): 00:00:00.0073955
By .Max (2): 00:00:00.0111658

By desc (3): 00:00:00.0066200
By .Max (3): 00:00:00.0115127

By desc (4): 00:00:00.0071220
By .Max (4): 00:00:00.0119572

By desc (5): 00:00:00.0070341
By .Max (5): 00:00:00.0114320

By desc (6): 00:00:00.0066670
By .Max (6): 00:00:00.0111127

By desc (7): 00:00:00.0071905
By .Max (7): 00:00:00.0116715

By desc (8): 00:00:00.0065414
By .Max (8): 00:00:00.0118076

By desc (9): 00:00:00.0071662
By .Max (9): 00:00:00.0131962

LINQPad スクリプト全体を次に示します。

void Main()
{
    var listOfItems = new List<Item>();

    // Make 100000 Items with semirandom numbers
    for(int i=0; i<100000; i++)
    {
        listOfItems.Add(new Item { Number = i * DateTime.Now.Ticks });
    }

    for(int i=0; i<10; i++)
    {
        RunTest(i, listOfItems);
    }
}

void RunTest(int count, List<Item> listOfItems)
{
    var timer = new System.Diagnostics.Stopwatch();
    timer.Start();
    // Find by descending
    for(int i=0; i<100000; i++)
    {
        var itemWithLargestNumber = 
            from item in listOfItems
            orderby item.Number descending
            select item;
    }
    timer.Stop();
    string.Format("By desc ({0}): {1}", count, timer.Elapsed).Dump();

    timer = new System.Diagnostics.Stopwatch();
    timer.Start();

    // Find by .Max
    for(int i=0; i<100000; i++)
    {
        var itemWithLargestNumber = 
            from item in listOfItems
            where item.Number== (from l in listOfItems select item).Max(l => l.Number)
            select item;
    }
    timer.Stop();
    string.Format("By .Max ({0}): {1}", count, timer.Elapsed).Dump();

    "".Dump();
}

class Item 
{
    public long Number { get; set; }
}
于 2012-10-02T09:29:27.833 に答える
0

どちらも一連のアイテムを返します。私は使うだろう:

var max = listOfItems.OrderByDescending(item => item.Number).FirstOrDefault();

次に、クエリの実行計画が何であるかを確認します。LINQ to Objects では比較的非効率的ですが、生成された SQL と、それがデータベース側で実際に何を意味するのかを実際に確認する必要があります。

于 2012-10-02T09:08:46.840 に答える