Ich habe dies bereits für bestimmte Indizes getan, um häufig ausgeführte Abfragen zu unterstützen. Tatsächlich haben sie mehrere Clustered-Indizes erstellt: Wenn einer dieser Indizes zum Auffinden von Zeilen verwendet wird, ist keine zusätzliche Arbeit erforderlich, um den Rest der Daten im realen Clustered-Index (oder im Heap, wenn kein realer Clustered-Index vorhanden ist) nachzuschlagen. .
Ist das eine vernünftige Strategie?
Für einige Indizes, bei denen bestimmte Abfragemuster unterstützt werden müssen, sicherlich ja.
Aber um dies mit allen Indizes zu tun , würde ich genauso sicher nein sagen.
Es wird viel Platz verschwenden, wo es nicht wirklich benötigt wird, und Einfügungen / Aktualisierungen werden erheblich verlangsamt. Es kann so viele Leseabfragen verlangsamen, wie es auch hilft, da jede Indexseite weniger Datensätze enthält, sodass jede Abfrage, die zum Filtern auf einen Teil des Index verweisen muss, aber nicht alle anderen Spalten verwendet, auf mehr Seiten zugreifen muss. Dadurch wird Ihre Datenbank speicherhungriger: Diese Seiten müssen in den Pufferpool geladen werden, wodurch möglicherweise andere nützliche Seiten ausgeworfen werden, wenn der Arbeitsspeicher knapp ist. Wenn für diese Indizes eine Komprimierung verwendet wird, um die Auswirkungen auf die Speicher- und Speicheranforderungen zu verringern, werden stattdessen die CPUs zusätzlich belastet.
Der Zugriff erfolgt über ein ORM, das standardmäßig (aber nicht immer) alle Spalten abruft
Dies ist ein häufiges Muster mit schlecht optimierter Verwendung eines ORM (oder nur naiver ORMs). In diesen Fällen habe ich gesehen, dass der Indexberater von SQL Server (und ähnliche Tools von Drittanbietern) Indizes mit vielen INCLUDE
d-Spalten vorschlägt , daher stimme ich Ihrem zu Vorschlag, dass aus diesem Grund die Indizes auf diese Weise erstellt wurden.
Obwohl all diese Abfragen dadurch möglicherweise etwas schneller und einige erheblich schneller werden, vermute ich, dass in vielen Fällen der Nutzen so gering ist, dass er den zusätzlichen Speicherbedarf, den Ihr gemeinsamer Arbeitssatz, der Speicherplatz auf der Festplatte und der Festplatte benötigen, nicht wert ist die E / A zwischen Festplatte und Speicher.
Denken Sie auch daran, dass der ORM möglicherweise nicht alle Spalten aller Tabellen auswählt, die eine Abfrage berührt, sodass der Vorteil möglicherweise nur für das Hauptziel der aktuellen Anforderung gilt und die größeren Indizes die Abfrage möglicherweise benachteiligen, wenn andere Objekte zum Filtern verwendet werden aber keine Daten zurückgeben ( SELECT * FROM table1 WHERE id IN (SELECT someID FROM table2 WHERE someColumn='DesiredValue')
vielleicht).
Eine weitere Überlegung für den überschüssigen Speicherplatz, insbesondere wenn die Daten groß sind, besteht darin, dass er sich auf Ihre Sicherungsstrategie auswirkt: Speicher- und Übertragungskosten für diese Sicherungen, potenzielle Wiederherstellungszeiten usw.
sollten wir auf Unterschiede zwischen den beiden vorbereitet sein [on-prem & AzureSQL]
Im Allgemeinen denke ich, dass die Überlegungen hier in jedem Fall gleich sein werden, obwohl überschüssige Speicher- / E / A-Kosten, die durch die großen Indizes verursacht werden, in Azure möglicherweise direkter sichtbar sind, wo Sie die Serviceebene und damit die Infrastrukturkosten einfacher anpassen können als mit einem relativ festen Satz von Hardwareressourcen. Wenn Sie Standard- / Premium-Ebenen anstelle von vcore-basierten Preisen verwenden, sind Sie stärker von den Standard-E / A-Kosten betroffen, da Premium deutlich mehr E / A pro DTU enthält. Wenn Sie in Azure Sicherungen oder Redundanzen für mehrere Regionen oder andere nicht lokale Funktionen verwenden, entstehen möglicherweise Bandbreitenkosten, die mit dem zusätzlichen Speicherplatz verbunden sind, den ungewöhnlich große Indizes beanspruchen.
SELECT
ohne AngabeORDER BY
dieselben Zeilen wie zuvor zurückgegeben wurden, jedoch mit einer anderen willkürlichen Reihenfolge.In den meisten Fällen ist dies keine vernünftige Strategie. Der Grund dafür ist, dass in allgemeinen OLTP-Datenbanken die an den Endbenutzer zurückgegebenen Zeilen nicht viel sein werden. (Verallgemeinerung)
Die Frage, die Sie sich stellen sollten, lautet: Wenn Sie in den Schlüsselspalten suchen, wie viele Zeilen werden von dieser Suchoperation zurückgegeben? Wiederholen Sie dies für die Suchanfragen in dieser Spalte.
Betrachten Sie die folgende Tabelle, in der viele Spalten zurückgegeben werden.
where SelectiveIDField= ...
Wenn nur eine Zeile von der Suche zurückgegeben wird
selectiveIDField
, ist die zusätzliche Schlüsselsuche so eine schlechte Sache? (Vermutlich haben Sie hier Indizes geclustert, andernfalls RID-Suche)Es wird nur eine zusätzliche Schlüsselsuche, eine zusätzliche Ausführung + der Join-Operator durchgeführt. Selbst wenn es 10 oder sogar 100 sind, wäre es eine so große Auswirkung? Dies hängt auch davon ab, wie oft Ihre Abfrage ausgeführt wird und wie wichtig die Ausführungszeit ist.
Wenn es vernachlässigbar ist, erstellen Sie einfach den Index
SelectiveIDField
und nennen Sie ihn einen Tag. Es sollte die Lesegewinne im Vergleich zu den Schreibverlusten nicht wert sein.Kurz gesagt, das Erstellen von Indizes für die gesamte Tabelle sollte meiner Meinung nach kein Standardansatz sein, es sei denn, Sie sehen wirklich ein Problem mit einer Abfrage und können es drastisch verbessern, indem Sie einen gesamten Abdeckungsindex hinzufügen.
quelle