Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/312.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:性能数据库查询仅查询每n个元素_C#_Asp.net_Linq_Asp.net Web Api - Fatal编程技术网

C# Linq:性能数据库查询仅查询每n个元素

C# Linq:性能数据库查询仅查询每n个元素,c#,asp.net,linq,asp.net-web-api,C#,Asp.net,Linq,Asp.net Web Api,我正在从事一个个人项目,在这个项目中,我需要一些关于数据库性能Linq查询的帮助。所讨论的数据库可能有数百万个日志条目,通过API Asp,我希望有一个选项,仅将这些日志的代表性子集返回到图形界面 下面是有问题的方法: public IEnumerable<Log> GetByParameter(int ParameterID,DateTime timeStart, DateTime timeEnd) { return _context.Logs.Where

我正在从事一个个人项目,在这个项目中,我需要一些关于数据库性能Linq查询的帮助。所讨论的数据库可能有数百万个日志条目,通过API Asp,我希望有一个选项,仅将这些日志的代表性子集返回到图形界面

下面是有问题的方法:

public IEnumerable<Log> GetByParameter(int ParameterID,DateTime timeStart, DateTime timeEnd)
    {
        return _context.Logs.Where
            (a => a.ParameterID == ParameterID && 
            (DateTime.Compare(a.LogDate,timeStart) > 0 && DateTime.Compare(a.LogDate,timeEnd) < 0)).ToList();
    }
请注意,该方法采用两个DateTimes作为参数,这会产生一个查询日志的时间范围

我希望像这样扩展此方法:

public IEnumerable<Log> GetByParameter(int ParameterID,DateTime timeStart, DateTime timeEnd, int limit)
例如,给定传递的参数,DB可能包含200万个条目,API使用者的限制可能是40000个条目。因此:

numberOfEntries/limit=n

2*106/4*104=50

在本例中,我希望将每个第50个元素返回给API的使用者,元素之间的时间间隔相等

一种简单的方法是在给定参数的情况下查询整个表,然后过滤掉,但这看起来很混乱,与这种方法有点背道而驰,可能也非常无效

所以我的问题是:是否有任何方法可以编写一个查询,使它只查询每N行的DB


提前谢谢

你可以采取的一种方法是在某种指数上使用模数。如果你已经有了一个自动生成的Id,可以使用它——但这并不理想,因为你不能依赖它的连续性

您可以使用RANK在视图中创建索引列,但不幸的是,您不能直接从EF代码中使用RANK

如下所示:

var interval = 5; 
return _context.Logs
    .Where(a => 
        a.ParameterID == ParameterID &&
        (
           DateTime.Compare(a.LogDate,timeStart) > 0 && 
           DateTime.Compare(a.LogDate,timeEnd) < 0) &&
        a.Id % interval == 0).ToList(); //Filter on modulus of an index


不过,在本例中,我个人会使用SQL编写查询。

您可以使用SQL Server窗口函数(如row\u number:

WITH x AS
(
    SELECT ROW_NUMBER() over (order by LogDate) as rn, *
    FROM MyTable
    WHERE
        ParameterID = @ParameterID AND
        LogDate > @StartDate AND
        LogDate < @EndDate
)
SELECT * from X WHERE rn % 50 = 0
但有必要检查实际的执行计划,我想它不会是最优的

不要忘记在LogDate上创建索引


老实说,我不确定SQL Server是否是存储日志的好选择,我希望使用类似弹性的工具。

您使用的是什么数据库?SQL server?您被限制使用LINQ EF有什么原因吗???@Oliver不具体,除了我编写的其他代码使用LINQ之外,我想学习语法。我可以访问数据库,也可以编写SP。Linq有Skipi和Takei。有了它,你就可以得到寻呼了。有一个答案,你也可以用在一个可查询的。但是,您必须测试它,因为它可能会在客户端执行。至于你的实际要求,我认为你不应该做你想做的事。您试图任意降低样本,这将导致许多其他问题。在这里正确的做法是将结果分页。在性能方面,当您处理这么多行时,这主要取决于数据和索引等的性质,而不是LINQ。
var data = _context.Logs
    .Select((x, i) => new { Data = x, Number = i })
    .Where(x => x.Number % 50 == 0)
    .Select(x => x.Data);