2016-11-08 3 views
2

Ich benutze Aspnet-Core, Ef-Core mit SQL-Server. Ich habe eine Entität "Auftrag". Da ich erwarte, dass die Auftragstabelle groß ist und eine häufigste Abfrage die aktiven Aufträge nur für bestimmte Kunden erhält (aktive Aufträge sind nur ein winziger Bruchteil der gesamten Tabelle), möchte ich die Geschwindigkeit der Abfrage optimieren, aber ich kann aus diesen zwei Ansätzen entscheiden:ef-core - Bool Index vs historische Tabelle

1) Ich weiß nicht, ob dies möglich ist, da ich das vorher nicht getan habe, aber ich überlegte, eine boolesche Spalte mit dem Namen 'IsActive' zu erstellen und daraus einen Index zu machen Bei der Abfrage würden nur aktive Aufträge schneller sein.

2) Wenn eine Bestellung nicht aktiv ist, verschieben Sie die Bestellung in eine andere Tabelle, d. H. HistoricalOrders, wodurch die Tabelle der Bestellungen klein gehalten wird.

Welche der beiden hätte bessere Ergebnisse? Oder nichts davon ist eine gute Lösung und ein dritter Ansatz könnte vorgeschlagen werden?

+0

können Sie zeigen die Linq-Abfrage im Moment? – Sampath

+0

@Sampath Haven't schrieb es noch nicht, aber für den ersten Ansatz wäre es etwa so: _context.Set () .Wo (o => o.IsActive == true) –

Antwort

-1

Bevor Sie über die neue Tabelle HistoricalOrders nachdenken, erstellen Sie einfach einen Spaltennamen IsActive und testen Sie es mit Ihren Daten.Sie müssen es nicht als Index Spalte.B'cos Indizes verbrauchen Speicher und es verlangsamt schreibt und updates.So müssen wir sehr vorsichtig, wenn wir einen Index erstellen.Wenn Sie die Daten abfragen tun Sie es wie unten gezeigt.Auf der unteren Abfrage, wo Daten Auswahl (oder Filter) auf der SQL-Srever-Seite (IQueryable) getan wird. So ist es sehr schnell.

Hinweis: Verwenden Sie AsNoTracking() too.It wird auch die Leistung steigern.

var activeOrders =_context.Set<Orders>().Where(o => o.IsActive == true).AsNoTracking() 
.ToList(); 

Referenz:AsNoTracking()

+0

Sie brauchen immer noch einen Index über die 'IsActive'-Spalte, um einen Tabellenscan zu vermeiden. – thoean

+0

Indizes essen Speicher und es verlangsamt schreibt und updates.So müssen wir sehr vorsichtig, wenn wir einen Index erstellen @thoean – Sampath

+2

@usr Sampath hat mir geholfen, zwischen den beiden in meiner Frage genannten Ansätze zu entscheiden. Aber ich wäre daran interessiert, andere Lösungen zu hören. Könnten Sie bitte eine Alternative vorschlagen? –

0

Wenn Sie kalt Daten partitionieren entfernt dann ein führender boolean Indexspalte ist eine gültige Art und Weise, das zu tun. Diese Spalte muss zu allen Indizes hinzugefügt werden, die Sie als Warm/Kalt-Partition verwenden möchten. Dies umfasst den gruppierten Index. Das ist ziemlich peinlich. Für den Abfrageoptimierer müssen Sie ein Dummy-Prädikat where IsActive IN (0, 1) hinzufügen, damit es weiterhin nach solchen Indizes suchen kann. Natürlich wird dies nun auch die kalten Daten berühren. Sie müssen also wahrscheinlich den konkreten Wert von IsActive kennen oder versuchen Sie zuerst den 1 Wert und stellen Sie sicher, dass es 99% der Zeit entspricht.

Je nach Schema kann dies unpraktisch sein. Ich habe nie einen guten Fall dafür gesehen, aber ich bin mir sicher, dass es existiert.

Eine andere Möglichkeit ist die Partitionierung. Hier wird der Abfrageoptimierer verwendet, um mehrere Partitionen trotzdem zu untersuchen, aber Sie möchten auch nicht, dass er kalte Daten untersucht. Selbst wenn es nichts findet, wird dies Seiten in den Speicher ziehen, was die Partitionierung unmöglich macht.

Die historische Tabelle Idee (z. B. HistoricalOrders) ist das gleiche in verschiedenen Kleidern.

Also, um diese Arbeit zu machen Sie brauchen:

  1. alle Indizes ändern, die Sie im Begriff sind (wahrscheinlich alle) oder Partition oder eine History-Tabelle erstellen.
  2. Haben Sie einen Weg, fast nie die kalte Partition zu untersuchen.

Ich denke, (2) tötet es für die meisten Fälle.

Unter den 3 Lösungen würde ich wahrscheinlich die Indexlösung wählen, weil es am einfachsten ist. Wenn du dir Sorgen machst, dass Leute Fehler machen, indem du ständig schlechte Anfragen schreibst, würde ich mir eine separate Tabelle aussuchen. Das macht Fehler schwierig, macht den Code jedoch ziemlich umständlich.

Beachten Sie, dass viele Indizes bereits natürlich partitioniert sind. Indizes in der Identitätsspalte oder in einer steigenden Datetime-Spalte sind am Ende heiß und an anderer Stelle kalt. Ein Index auf (OrderStatus INT, CreateDateTime datetime2) hätte einen Hotspot pro Bestellstatus und wäre sonst kalt. So sind diese schon gelöst.

Some further discussion.