Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/337.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何使LINQ查询更快?_C#_Performance_Linq - Fatal编程技术网

C# 如何使LINQ查询更快?

C# 如何使LINQ查询更快?,c#,performance,linq,C#,Performance,Linq,modelData在列表中有100000项 我在2个循环中进行2次“选择” 它的结构是否会有所不同?因为它需要很长的时间-10分钟 public class ModelData { public string name; public DateTime DT; public int real; public int trade; public int position; public int dayPnl; } List<ModelData

modelData在列表中有100000项

我在2个循环中进行2次“选择”

它的结构是否会有所不同?因为它需要很长的时间-10分钟

public class ModelData
{
    public string name;
    public DateTime DT;
    public int real;
    public int trade;
    public int position;
    public int dayPnl;
}

List<ModelData> modelData;

var dates = modelData.Select(x => x.DT.Date).Distinct();
var names = modelData.Select(x => x.name).Distinct();

foreach (var aDate in dates)
{
    var dateRealTrades = modelData.Select(x => x)
                                  .Where(x => x.DT.Date.Equals(aDate) && x.real.Equals(1));

    foreach (var aName in names)
    {
        var namesRealTrades = dateRealTrades.Select(x => x)
                                            .Where(x => x.name.Equals(aName));

        // DO MY PROCESSING
    }
}
公共类模型数据
{
公共字符串名称;
公共日期时间;
公共不动产;
公共贸易;
公共职位;
公共国际日;
}
列出模型数据;
var dates=modelData.Select(x=>x.DT.Date).Distinct();
var name=modelData.Select(x=>x.name).Distinct();
foreach(日期中的var aDate)
{
var dateRealTrades=modelData.Select(x=>x)
其中(x=>x.DT.Date.Equals(aDate)和&x.real.Equals(1));
foreach(名称中的var aName)
{
var namesRealTrades=dateRealTrades.Select(x=>x)
其中(x=>x.name.Equals(aName));
//做我的处理
}
}

您可以像这样重写for循环:

foreach (var namesRealTrades in names.Select(aName => dateRealTrades.Where(x => x.name.Equals(aName))))
{
   //DO STUFF
}

根据您的数据,这可以减少您必须进行的查询数量

您是否尝试按照MSDN网站上的建议编译您的查询

当您有一个执行结构相似的应用程序时 查询很多时候,通常可以通过编译来提高性能 查询一次,然后以不同的方式执行多次 参数。例如,应用程序可能必须检索所有 位于特定城市的客户,该城市在 用户在窗体中执行的运行时。LINQtoSQL支持使用 为此目的编译的查询


我相信,使用group by进行两次查询就可以实现您的目标。一个用于按日期创建查找,另一个用于为您命名日期分组项

var data = modelData.Where(x => x.real.Equals(1))
                    .GroupBy(x => new { x.DT.Date, x.name });
var byDate = modelData.Where(x => x.real.Equals(1))
                      .ToLookup(x => x.DT.Date);

foreach(var item in data)
{
    var aDate = item.Key.Date; 
    var aName = item.Key.name;
    var namesRealTrades = item.ToList();
    var dateRealTrades = byDate[aDate].ToList();

    // DO MY PROCESSING
}
第一个查询将为您提供按名称和日期分组的项,以进行迭代,第二个查询将为您提供查找,以获取与给定日期关联的所有项。第二种方法使用查找,以便列表迭代一次,并使您能够快速访问结果项列表

这将大大减少您对当前拥有的
modelData
的迭代次数。

以下几点:

  • 使用.ToList()计算一次序列,以便以后保存
  • 使用.GroupBy()避免在modelData中重新搜索已找到的内容

    // Collections of models having the same Date or Name.
    var dates = modelData.GroupBy(x => x.DT.Date);
    var names = modelData.GroupBy(x => x.Name);
    
    foreach (var modelsWithDate in dates)
    {
       var aDate = modelsWithDate.Key;
       var dateRealTrades = modelsWithDate.Where(x => x.real == 1).ToList();
    
       foreach (var modelsWithName in names)
       {
           var aName = modelsWithName.Key;
           var namesRealTrades = modelsWithName.ToList();
    
           // DO MY PROCESSING
       }
    }
    

代码无效的方式有两种

  • 名称已改变了评估。每次迭代它时,它都必须遍历整个数据才能再次找到所有不同的名称。你应该保存结果
  • 您可以从集合中找到不同的值,然后再次检查集合中每个不同的值并查找其出现的情况。您应该使用分组
重写后的代码可以如下所示

    var dates = modelData.GroupBy(x => x.DT.Date);
    var names = modelData.Select(x => x.name).Distinct().ToArray();

    foreach (var date in dates)
    {
        var dateRealTrades = date.Where(x => x.real.Equals(1)).ToArray();
        var namesRealTradesLookup = dateRealTrades.ToLookup(x => x.name);

        foreach (var aName in names)
        {
            var namesRealTrades = namesRealTradesLookup[aName];

            // DO MY PROCESSING
            // var aDate = date.Key;
        }
    }
如果您对日期/名称组合不感兴趣,并且没有真正的交易,那么可以用更直接的方式完成

    var realModelData = modelData.Where(x => x.real.Equals(1));

    foreach (var dateRealTrades in realModelData.ToLookup(x => x.DT.Date))
    {
        foreach (var namesRealTrades in dateRealTrades.ToLookup(x => x.name))
        {

            // DO MY PROCESSING
            //var aDate = dateRealTrades.Key;
            //var aName = namesRealTrades.Key;
            //foreach(var trade in namesRealTrades) { ...
            //foreach(var trade in dateRealTrades) { ...
        }
    }

您可以删除
。首先选择(x=>x)
。我认为您只需要一个按日期然后按名称分组的查询。不必要或冗余的
。不同的
可能会影响性能。这通常会强制对底层数据进行排序。确保没有其他方法来完成同样的事情。在foreach之前应该执行where子句x.real.Equals(1)。除了优化Linq查询外,还应该确保在相关的DB字段上有一个覆盖索引。这可能会使您的过程加快90%以上。10万行真的不是一个很大的数字。我不明白为什么这会使它更快-请解释一下好吗?根据您的数据,它会减少对数据库的查询调用数量。唯一确定的方法是尝试将ToList()添加到var dates=modelData.GroupBy(x=>x.DT.Date)中;下一行将确保在循环它们之前将它们拉入内存。如果你看这个问题,modelData已经是一个列表了。一切都在记忆中,谢谢。但对于每个日期,我还需要最后一个“职位”和“dayPnl”。我如何调整您的代码以添加这些内容?@ManInMoon您是说您在
//执行我的处理
中使用
dateRealTrades
?我已更新为包含第二个查询,以便您按日期查找项目。