Reputation: 99
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.
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;
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;
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.
Upvotes: 0
Views: 106
Reputation: 103575
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.
Upvotes: 2