Ich verbinde eine kleine Tabelle (1.000 Zeilen) mit einer großen Tabelle (8 Millionen Zeilen) in SQL Server 2008. Der Join verwendet einen nicht gruppierten Abdeckungsindex für die große Tabelle, und der Join kann drei mögliche Abfragepläne erstellen. Ich versuche herauszufinden, welcher Plan besser ist, aber ich möchte dieses Wissen auch verallgemeinern, damit ich beim nächsten Mal besser wissen kann, welche Heuristiken beim Betrachten von SQL-E / A-Statistiken verwendet werden sollen.
Plan Nr. 1 ist ein Loop-Join und gibt Statistiken für die große Tabelle wie folgt aus:
Scan count 2582, logical reads 35686, physical reads 1041, read-ahead reads 23052
Plan 2 ist ein Zusammenführungs-Join und gibt Statistiken wie folgt aus:
Scan count 1, logical reads 59034, physical reads 49, read-ahead reads 59004
Plan Nr. 3 ist ein Hash-Join und gibt Statistiken wie folgt aus:
Scan count 3, logical reads 59011, physical reads 5, read-ahead reads 59010
Der Deckungsindex ist geordnet nach (ID, Date)
. Die Abfrage gibt Daten für ungefähr 50% der IDs zurück und gibt für jede ID einen zusammenhängenden Teil der Daten der letzten 3 Monate zurück, der normalerweise ungefähr 1/4 oder die Zeilen für jede ID beträgt. Die Abfrage gibt ungefähr 1/8 der gesamten Zeilen im Index zurück. Mit anderen Worten, die Abfrage ist spärlich, aber konsistent.
Ich gehe davon aus, dass Plan Nr. 1 für diese Arbeitslast schrecklich ist, da das Bewegen des Plattenkopfs um das 2.500-fache (oder sogar 1.041-fache) weitaus teurer ist als ein sequentieller Platten-Scan. Ich gehe auch davon aus, dass # 3 und # 2 ähnliche, sequentielle (und daher effizientere) E / A-Muster haben.
Aber gibt es einen Fall, in dem Plan 1 wirklich am besten ist, in dem "am besten" weniger Auswirkungen auf das E / A-Subsystem und weniger Auswirkungen auf andere gleichzeitig ausgeführte Abfragen bedeutet?
Oder hängt es wirklich von vielen Variablen ab, wie der Art meines Festplattensubsystems, der Indexfragmentierung usw. Wenn "es davon abhängt", gibt es Faustregeln, um das Problem anzugehen?
quelle
Antworten:
Hier ist der Killer-Deal: Im Januar kostete der Kauf von 864 * GB * RAM 12.000 US-Dollar . Sie können viel Geld verdienen, indem Sie einfach den Arbeitsspeicher Ihres Servers so weit erhöhen, dass Sie nie mehr physisch gelesen werden (natürlich nach dem Aufwärmen).
Abgesehen davon ist es wirklich schwierig, eine schwarze oder weiße Meinung zu einem der von Ihnen präsentierten Datenpunkte abzugeben. Sicher, Plan Nr. 1 hatte die meisten physischen Lesevorgänge, aber sind Sie sicher, dass alle Tests mit einem ähnlich aufgewärmten Cache durchgeführt wurden? Könnte es sein, dass # 1 den Cache für # 2 aufgewärmt hat. Was ist Ihre Testmethode, um sicherzustellen, dass alle Fälle auf ebenem Boden berücksichtigt werden? Aber wenn Sie 500 US-Dollar berappen und den Arbeitsspeicher verdoppeln würden, wäre das dann noch wichtig? # 1 hat die am wenigsten logischen Lesevorgänge ...
Aber dann profitiert # 2 wahrscheinlich von einem hohen DOP (dass ein Scan parallel sein kann). Ist die Wanduhrzeit von # 2 besser als # 1, nachdem Sie ausreichend RAM hinzugefügt haben?
Wie viele dieser Pläne laufen parallel? Gibt es Dutzende von Abfragen, die gleichzeitig eine signifikante Speicherzuweisung für den Hash von # 3 anfordern und somit einen Konflikt für RESOURCE_SEMAPHORE erzeugen? Führt die Nummer 2 eine Sortierung durch und fordert sie auch eine Speicherzuweisung an? Funktioniert # 1 besser, da kein Zuschuss erforderlich ist (zumindest aus den veröffentlichten Informationen ...)?
Ist wirklich sehr, sehr relativ und die Frage, die Sie stellen, ähnelt eher der Suche nach einer Lösung für ein komplexes Gleichungssystem ... es könnte einfach mehr als eine Lösung geben.
Eines ist sicher: 8 Millionen Zeilen sollten in den Arbeitsspeicher passen und viel Platz bieten. Diese physischen Lesevorgänge betteln um einige Speicherbänke.
quelle
Für diese scheinbar sehr einfache Abfrage erstellt der Optimierer konsistent den besten Plan gemäß seinem Kostenmodell. Das Kostenmodell ist ziemlich genau. Meine Empfehlung wäre also, die Auswahl SQL Server zu überlassen.
Zweite Empfehlung: Messen Sie die Abfragedauer für alle drei Varianten mit einem Hot-Cache. Dann entscheiden. (Entscheiden Sie sich nicht aufgrund von Lesevorgängen und Scans und dergleichen. Was für Sie wichtig ist, ist die Dauer.)
Um den besten Join-Typ (oder die besten Indizes) auszuwählen, müssen Sie im Allgemeinen wissen, wie die Join-Algorithmen funktionieren. Das sind zu viele Informationen, um sie hier zu posten.
quelle
Scananzahl ignorieren, das ist nicht wichtig. Konzentrieren Sie sich darauf, wie Sie die logischen Lesevorgänge senken können. Basierend auf http://www.practicalsqldba.com/2013/07/sql-server-performance-tuning.html .
quelle