2016-05-30 6 views
2

Ich habe PostgreSQL läuft zusammen mit EF7.Am wenigsten teure Operation, um nach neuen Aufzeichnungen in der Tabelle mit EF zu suchen

Meine Tabellenstruktur:

  • Id (bigint)
  • Inhalt (Text)
  • CreatedAt (Zeitstempel ohne Zeitzone NOT NULL)

ich in meinem Frontend unendlich Scroll haben App und Abfrageergebnisse mit .Skip (n) & .Aufnahme (m). I.e.

.Skip(0), .Take(10); 
.Skip(10), .Take(10); 
.Skip(20), .Take(10); 
<...> 

nun beim Scrollen, wenn es neuere Aufzeichnungen sind, dann muss ich wissen, wie viele und fügen Sie (n) Funktion .skip. Ich muss sie nicht anzeigen, sondern muss sie beim Überspringen berücksichtigen.

Zeit für sie Ich überprüfe wie so doch sollte dies scheinbar ziemlich teuer sein, nachdem Tabelle 50k-100k Aufzeichnungen überschreiten:

_myRepository.GetAll().Where(x => x.CreatedAt > newestActivityDate).Count(); 

GetAll():

public IQueryable<Activity> GetAll() 
{ 
    return _context.Activities.OrderByDescending(x => x.CreatedAt); 
} 

Was wäre die beste (performanteste) Operation, um zu überprüfen, ob neue Datensätze vorhanden sind & Wie viele? Nach Datum prüfen und nur dann zählen, wenn neue Datensätze vorhanden sind?

EDIT: GetAll() Beschreibung für mehr Klarheit hinzugefügt.

+0

Liefert 'GetAll() '' IQueryable'? – haim770

+0

Ja, GetAll() gibt IQueryable zurück – ign

+1

Wenn Sie "nextActivityDate" immer wissen - eine Option besteht darin, Ihre Abfragen nur mit Where (x => c.CreatedAt <= nextActivityDate) zu begrenzen. Dann wird die Suche nach neuen Datensätzen überflüssig. – Evk

Antwort

1

Ich weiß nicht, was Ihre .GetAll() Methode tut, so dass wirklich der Kern Ihres Problems ist.

LINQ hat, was deferred execution genannt wird. Das bedeutet, dass die Abfrage erst ausgeführt wird, wenn die Ergebnisse bearbeitet wurden. Wenn Sie eine SQL-Abfrage erstellen, wird nichts an die Datenbank gesendet, bis Sie damit fertig sind.

Also, wenn Ihre .GetAll() Methode mit einem .ToList() in dort abfragt, dann wird es alles aus der Datenbank ziehen, bevor Sie den Rest Ihrer Filterung hinzufügen. In diesem Fall, ja, wird es sehr teuer sein.

Sie können jedoch umgehen, indem Sie nur für die Zählung bitten. Sie haben das meiste schon eingerichtet.

Wenn Sie eine neue Methode in Ihrem Repository wie folgt hinzu:

public int GetNewRecordsCount(DateTime newestActivityDate) 
{ 
    _context.Widgets.Count(x => x.CreatedAt > newestActivityDate); 
} 

Dann wird dies eine andere SQL-Abfrage erstellen, die nur etwas ähnliches wie das ist:

SELECT COUNT(*) 
FROM Widgets 
WHERE CreatedAt > newestActivityDate; 

Das ist ein sehr schnelle Operation, bei der die Datenbank die gesamte Filterung für Sie übernimmt. Die einzige Sache, die zu Ihrem Code zurückgegeben wird, ist nur ein einzelnes Zeilen-, einzelnes Spaltenresultat der Gesamtzählung.

+0

'Count' kann ein Kriterium annehmen und Sie brauchen' Wo' überhaupt nicht: D –

+0

Danke. Es ist ein freier Tag und ich bin gerade aufgewacht. – krillgar

+0

Kein Problem, ich wollte nur mit dieser Verbesserung zu Ihrer Antwort beitragen;) –

Verwandte Themen