哪个查询具有更好的性能,可以返回具有特定属性最大值的对象



哪个查询在返回具有特定属性的最大值的对象时具有更好的性能?

 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;

在 SQL 中,这两个查询被转换为(至少,如果您执行 .FirstOrDefault() 在生成的 IEnumerables 中选择所需的对象):

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 个半随机数,每种查询方式 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; }
}
好吧,

这两个都返回一系列项目。我会使用:

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

然后检查查询的执行计划是什么。在 LINQ to Object 中,效率相对较低,但您确实需要查看生成的 SQL,以及它在数据库端的真正含义。

最新更新