Modellieren der LeistungModeling for Performance

In vielen Fällen kann die Art und Weise, wie Sie modellieren, eine tiefgreifende Auswirkung auf die Leistung der Anwendung haben. ein ordnungsgemäß normalisiertes und "korrektes" Modell ist in der Regel ein guter Ausgangspunkt, aber in realen Anwendungen können einige pragmatische Kompromisse eine gute Leistung erzielen.In many cases, the way you model can have a profound impact on the performance of your application; while a properly normalized and "correct" model is usually a good starting point, in real-world applications some pragmatic compromises can go a long way for achieving good performance. Da es ziemlich schwierig ist, das Modell zu ändern, sobald eine Anwendung in der Produktion ausgeführt wird, sollten Sie die Leistung beim Erstellen des anfänglichen Modells berücksichtigen.Since it's quite difficult to change your model once an application is running in production, it's worth keeping performance in mind when creating the initial model.

Denormalisierung und CachingDenormalization and caching

Denormalization ist die Vorgehensweise, dem Schema redundante Daten hinzuzufügen, in der Regel, um Joins bei Abfragen auszuschließen.Denormalization is the practice of adding redundant data to your schema, usually in order to eliminate joins when querying. Beispielsweise müssen Sie für ein Modell mit Blogs und Beiträgen, in denen jeder Beitrag eine Bewertung hat, häufig die durchschnittliche Bewertung des Blogs anzeigen.For example, for a model with Blogs and Posts, where each Post has a Rating, you may be required to frequently show the average rating of the Blog. Die einfache Vorgehensweise würde die Beiträge nach Ihrem Blog gruppieren und den Durchschnitt als Teil der Abfrage berechnen. dafür ist jedoch ein kostspieliger Join zwischen den beiden Tabellen erforderlich.The simple approach to this would group the Posts by their Blog, and calculate the average as part of the query; but this requires a costly join between the two tables. Die Denormalisierung würde den berechneten Durchschnitt aller Beiträge zu einer neuen Spalte im Blog hinzufügen, sodass Sie sofort zugänglich ist, ohne zu beitreten oder zu berechnen.Denormalization would add the calculated average of all posts to a new column on Blog, so that it is immediately accessible, without joining or calculating.

Die oben genannten können als Form der zwischen Speicherung angezeigt werden: aggregierte Informationen aus den Beiträgen werden in Ihrem Blog zwischengespeichert. ebenso wie bei jedem Caching besteht das Problem darin, dass der zwischengespeicherte Wert mit den Daten, die zwischengespeichert werden, auf dem neuesten Stand gehalten wird.The above can be viewed as a form of caching - aggregate information from the Posts is cached on their Blog; and like with any caching, the problem is how to keep the cached value up to date with the data it's caching. In vielen Fällen ist es in Ordnung, dass die zwischengespeicherten Daten für ein wenig verzögert werden. im obigen Beispiel ist es in der Regel sinnvoll, dass die durchschnittliche Bewertung des Blogs an einem bestimmten Punkt nicht vollständig auf dem neuesten Stand ist.In many cases, it's OK for the cached data to lag for a bit; for example, in the example above, it's usually reasonable for the blog's average rating to not be completely up to date at any given point. Wenn dies der Fall ist, können Sie die Anwendung jetzt alle und dann neu berechnen. Andernfalls muss ein aufwendiges System eingerichtet werden, damit die zwischengespeicherten Werte auf dem neuesten Stand gehalten werden.If that's the case, you can have it recalculated every now and then; otherwise, a more elaborate system must be set up to keep the cached values up to date.

Im folgenden werden einige Verfahren für Denormalisierung und Caching in EF Core erläutert und auf die relevanten Abschnitte in der-Dokumentation verwiesen.The following details some techniques for denormalization and caching in EF Core, and points to the relevant sections in the documentation.

Gespeicherte berechnete SpaltenStored computed columns

Wenn die zwischengespeicherten Daten ein Produkt anderer Spalten in der gleichen Tabelle sind, kann eine gespeicherte berechnete Spalte eine perfekte Lösung sein.If the data to be cached is a product of other columns in the same table, then a stored computed column can be a perfect solution. Beispielsweise kann eine Customer FirstName -Spalte und eine- LastName Spalte enthalten, aber wir müssen möglicherweise nach dem vollständigen Namen des Kunden suchen.For example, a Customer may have FirstName and LastName columns, but we may need to search by the customer's full name. Eine gespeicherte berechnete Spalte wird automatisch von der Datenbank verwaltet. diese wird immer neu berechnet, wenn die Zeile geändert wird, und Sie können sogar einen Index darüber definieren, um Abfragen zu beschleunigen.A stored computed column is automatically maintained by the database - which recalculates it whenever the row is changed - and you can even define an index over it to speed up queries.

Aktualisieren von Cache Spalten bei Änderung von EingabenUpdate cache columns when inputs change

Wenn die zwischengespeicherte Spalte auf Eingaben von außerhalb der Tabellenzeile verweisen muss, können keine berechneten Spalten verwendet werden.If your cached column needs to reference inputs from outside the table's row, you cannot use computed columns. Es ist jedoch immer noch möglich, die Spalte neu zu berechnen, wenn die Eingabe geändert wird. Beispielsweise können Sie die Bewertung des durchschnittlichen Blogs jedes Mal neu berechnen, wenn ein Beitrag geändert, hinzugefügt oder entfernt wird.However, it is still possible to recalculate the column whenever its input changes; for example, you could recalculate the average Blog's rating every time a Post is changed, added or removed. Achten Sie darauf, die genauen Bedingungen zu identifizieren, wenn eine Neuberechnung erforderlich ist. andernfalls wird der zwischengespeicherte Wert nicht mehr synchronisiert.Be sure to identify the exact conditions when recalculation is needed, otherwise your cached value will go out of sync.

Eine Möglichkeit besteht darin, das Update selbst über die reguläre EF Core-API auszuführen.One way to do this, is to perform the update yourself, via the regular EF Core API. SaveChangesEreignisse oder Interceptors können verwendet werden, um automatisch zu überprüfen, ob Beiträge aktualisiert werden, und um die Neuberechnung auf diese Weise auszuführen.SaveChanges Events or interceptors can be used to automatically check if any Posts are being updated, and to perform the recalculation that way. Beachten Sie, dass dies in der Regel zusätzliche Datenbankroundtrips umfasst, da zusätzliche Befehle gesendet werden müssen.Note that this typically entails additional database roundtrips, as additional commands must be sent.

Bei größeren Leistungs sensitiven Anwendungen können Daten Bank Trigger definiert werden, um die Neuberechnung in der Datenbank automatisch auszuführen.For more perf-sensitive applications, database triggers can be defined to automatically perform the recalculation in the database. Dadurch werden zusätzliche Datenbankroundtrips eingespart, die automatisch innerhalb der gleichen Transaktion wie das Haupt Update ausgeführt werden, und es kann einfacher eingerichtet werden.This saves the extra database roundtrips, automatically occurs within the same transaction as the main update, and can be simpler to set up. EF bietet keine bestimmte API zum Erstellen oder Verwalten von Triggern, aber es ist ganz schön, eine leere Migration zu erstellen und die Triggerdefinition über RAW SQL hinzuzufügen.EF doesn't provide any specific API for creating or maintaining triggers, but it's perfectly fine to create an empty migration and add the trigger definition via raw SQL.

Materialisierte SichtenMaterialized views

Materialisierte Sichten ähneln regulären Sichten, mit dem Unterschied, dass Ihre Daten auf dem Datenträger ("MATERIALIZED") gespeichert werden und nicht jedes Mal berechnet werden, wenn die Sicht abgefragt wird.Materialized views are similar to regular views, except that their data is stored on disk ("materialized"), rather than calculated every time when the view is queried. Dieses Tool ist nützlich, wenn Sie einer vorhandenen Datenbank nicht einfach eine einzelne Cache Spalte hinzufügen möchten, sondern den gesamten Resultset der Ergebnisse komplexer und kostspieliger Abfragen so speichern möchten, als ob es sich um eine reguläre Tabelle handelt. Diese Ergebnisse können dann sehr kostengünstig abgefragt werden, ohne dass Berechnungen oder Joins ausgeführt werden.This tool is useful when you don't want to simply add a single cache column to an existing database, but rather want to cache the entire resultset of a complicated and expensive query's results, just as if it were a regular table; these results can then be queried very cheaply without any computation or joins happening. Im Gegensatz zu berechneten Spalten werden materialisierte Sichten nicht automatisch aktualisiert, wenn sich die zugrunde liegenden Tabellen ändern. Sie müssen manuell aktualisiert werden.Unlike computed columns, materialized views aren't automatically updated when their underlying tables change - they must be manually refreshed. Wenn die zwischengespeicherten Daten verzögert werden können, kann das Aktualisieren der Ansicht über einen Timer erfolgen. eine andere Möglichkeit besteht darin, Daten Bank Trigger so einzurichten, dass eine materialisierte Sicht nach bestimmten Daten Bank Ereignissen überprüft wird.If the cached data can lag, refreshing the view can be done via a timer; another option is to set up database triggers to review a materialized view once certain database events occur.

EF stellt derzeit keine bestimmte API zum Erstellen oder Verwalten von Sichten bereit, materialisiert oder anderweitig; Es ist jedoch ganz schön, eine leere Migration zu erstellen und die Sicht Definition über RAW SQL hinzuzufügen.EF doesn't currently provide any specific API for creating or maintaining views, materialized or otherwise; but it's perfectly fine to create an empty migration and add the view definition via raw SQL.

Vererbungs ZuordnungInheritance mapping

Es wird empfohlen, die dedizierte Seite zur Vererbung zu lesen, bevor Sie mit diesem Abschnitt fortfahren.It's recommended to read the dedicated page on inheritance before continuing with this section.

EF Core unterstützt derzeit zwei Verfahren zum Mapping eines Vererbungs Modells zu einer relationalen Datenbank:EF Core currently supports two techniques for mapping an inheritance model to a relational database:

  • Tabelle pro Hierarchie (TPH), in der eine gesamte .net-Hierarchie von Klassen einer einzelnen Datenbanktabelle zugeordnet wirdTable-per-hierarchy (TPH), in which an entire .NET hierarchy of classes is mapped to a single database table
  • Tabelle pro Typ (TPT), in der jeder Typ in der .net-Hierarchie einer anderen Tabelle in der Datenbank zugeordnet wird.Table-per-type (TPT), in which each type in the .NET hierarchy is mapped to a different table in the database.

Die Auswahl der Methode für die Vererbung von Vererbung kann eine beträchtliche Auswirkung auf die Anwendungsleistung haben. es wird empfohlen, vor dem Commit auf eine Auswahl sorgfältig zu messen.The choice of inheritance mapping technique can have a considerable impact on application performance - it's recommended to carefully measure before committing to a choice.

Manchmal wählen Sie TPT aus, da es sich anscheinend um die "saubere" Methode handelt. eine separate Tabelle für jeden .NET-Typ bewirkt, dass das Datenbankschema der .net-Typhierarchie ähnelt.People sometimes choose TPT because it appears to be the "cleaner" technique; a separate table for each .NET type makes the database schema look similar to the .NET type hierarchy. Da TPH die gesamte Hierarchie in einer einzelnen Tabelle darstellen muss, verfügen die Zeilen darüber hinaus über alle Spalten, unabhängig vom Typ, der tatsächlich in der Zeile gespeichert ist, und nicht verknüpfte Spalten sind immer leer und werden nicht verwendet.In addition, since TPH must represent the entire hierarchy in a single table, rows have all columns regardless of the type actually being held in the row, and unrelated columns are always empty and unused. Abgesehen davon, dass es sich um ein unreines Zuordnungs Verfahren handelt, sind viele davon überzeugt, dass diese leeren Spalten beträchtlichen Speicherplatz in der Datenbank beanspruchen und die Leistung beeinträchtigen können.Aside from seeming to be an "unclean" mapping technique, many believe that these empty columns take up considerable space in the database and may hurt performance as well.

Die Messung zeigt jedoch, dass TPT in den meisten Fällen die unterste Karten Methode aus Leistungs Sicht verwendet. Wenn alle Daten in TPH aus einer einzelnen Tabelle stammen, müssen TPT-Abfragen mehrere Tabellen miteinander verknüpfen, und Joins sind eine der primären Quellen für Leistungsprobleme in relationalen Datenbanken.However, measuring shows that TPT is in most cases the inferior mapping technique from a performance standpoint; where all data in TPH comes from a single table, TPT queries must join together multiple tables, and joins are one of the primary sources of performance issues in relational databases. Datenbanken neigen in der Regel auch zu leeren Spalten, und Features wie SQL Server sparsespalten können diesen Aufwand noch weiter reduzieren.Databases also generally tend to deal well with empty columns, and features such as SQL Server sparse columns can reduce this overhead even further.

Ein konkretes Beispiel finden Sie unter diesem Benchmarkwert , mit dem ein einfaches Modell mit einer Hierarchie von 7 Typen eingerichtet wird. 5000 Zeilen werden für jeden Typ mit der Grundlage von 35000 Zeilen in einem Seeding angezeigt, und der Vergleichstest lädt einfach alle Zeilen aus der Datenbank:For a concrete example, see this benchmark which sets up a simple model with a 7-type hierarchy; 5000 rows are seeded for each type - totalling 35000 rows - and the benchmark simply loads all rows from the database:

MethodeMethod MittelwertMean FehlerError StdDevStdDev Gen 0Gen 0 Gen 1Gen 1 Gen 2Gen 2 ZugeordnetAllocated
TPHTPH 132,3 ms132.3 ms 2,29 ms2.29 ms 2,03 MS2.03 ms 8000,00008000.0000 3000,00003000.0000 1250,00001250.0000 44,49 MB44.49 MB
TPTTPT 201,3 ms201.3 ms 3,32 MS3.32 ms 3,10 ms3.10 ms 9000,00009000.0000 4000,00004000.0000 - 61,84 MB61.84 MB

Wie Sie sehen können, ist TPH deutlich effizienter als TPT für dieses Szenario.As can be seen, TPH is considerably more efficient than TPT for this scenario. Beachten Sie, dass die tatsächlichen Ergebnisse immer von der bestimmten ausgeführten Abfrage und der Anzahl der Tabellen in der Hierarchie abhängen, sodass andere Abfragen möglicherweise eine andere Leistungslücke darstellen. Es wird empfohlen, diesen Vergleichs Code als Vorlage zum Testen anderer Abfragen zu verwenden.Note that actual results always depend on the specific query being executed and the number of tables in the hierarchy, so other queries may show a different performance gap; you're encouraged to use this benchmark code as a template for testing other queries.