简体   繁体   中英

Is there a more efficient way to use the Linq Last() command?

I have a huge PostgresDB machine data table (with TimeScale) and need to get the the last position of a machine. I know, the most efficient way would be a continuous aggregation each day with timescale and and save the last position. But that's not the point of this Question;)

So, I'm using Linq to do the SQL Request. I have tried some different Method to get the Last Position of the Machine, which I now explain below. I have to mention that the Duration of each function is that huge, because I'm testing it with a list of 60 machine.

  1. LINQ function last() -> Duration: 132s / Needs a lot of RAM because Last() is calculating outside of the Database. There is a huge data transfer between Database and Program because LINQ can't translate Last() to SQL.

     gpsPositionDto.Latitude = _context.MeasureValues.Last(c => c.MachineId == machine && c.MeasureValueId == 80).Value;
  2. LINQ function OrderByDescending().First() -> Duration: 114s / Database is needing RAM because the calculation is done inside the Database. So there is no huge data transfer between the Database and Program.

     gpsPositionDto.Latitude = _context.MeasureValues.OrderByDescending(c => c.Timestamp).First(c => c.MachineId == machine && c.MeasureValueId == 80).Value;
  3. LINQ function first() -> Duration: 30s / I know, this don't give me the right Value, but I wanted to try it out to see how long this needs.

     gpsPositionDto.Latitude = _context.MeasureValues.First(c => c.MachineId == machine && c.MeasureValueId == 80).Value;

Is there any possibility to get a similar Duration to first(), but that I get the correct Data? Because I will execute this function once an Hour for further calculation and we get more and more Machine's inside this List.

gpsPositionDto.Latitude = 
      _context.MeasureValues
              .Last(c => c.MachineId == machine && c.MeasureValueId == 80).Value;

This doesn't really have a meaning. Without an OrderBy , "First" and "Last" has no meaning. I tried replicating use cases using the Northwind database on Microsoft SQL Express. It wouldn't even let me do a .Last() on a table.

Orders.Last(o=>o.CustomerID == "TOMSP")

"NotSupportedException••• The query operator 'Last' is not supported."

Your option 2 worked fine:

Orders.OrderByDescending(o =>o.OrderDate ).First(o=>o.CustomerID == "TOMSP")

generating this SQL:

-- Region Parameters
DECLARE @p0 NVarChar(1000) = 'TOMSP'
-- EndRegion
SELECT TOP(1)[t0].[OrderID], [t0].[CustomerID],
             [t0].[EmployeeID], [t0].[OrderDate], 
             [t0].[ShipPostalCode], [t0].[ShipCountry]
FROM[Orders] AS[t0]
WHERE [t0].[CustomerID] = @p0
ORDER BY[t0].[OrderDate] DESC

It's possible that, for Option 1, Postgres is effective doing:

Orders.ToList().Last(o=>o.CustomerID == "TOMSP")

reading the entire table into memory, and then searching on it there, which could explain the bad timings for that.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM