Ich habe eine Legacy -Datenbank mit der folgenden Tabelle (Anmerkung: kein Primärschlüssel)
Es definiert jede eine Aufzeichnung für jede Unterkunft "Einheit" und Datum und den Preis für dieses Datum.
%Vor%Die Tabelle enthält ungefähr 16.500 Datensätze.
Aber ich muss die Daten in einem völlig anderen Format wie zB:
multiplizierenBis zu einer maximalen Dauer für jedes Ankunftsdatum.
Ich verwende die folgende Abfrage, um dies zu erreichen:
%Vor%Das funktioniert und gibt mir ungefähr 413.000 Datensätze. Die Ergebnisse dieser Abfrage, die ich verwende, um eine andere Tabelle zu aktualisieren.
Aber die Abfrage funktioniert ziemlich schlecht, wie Sie es bei so vielen Self-Joins erwarten würden. Es dauert ungefähr 15 Sekunden, um lokal zu laufen, aber auf unserem Testserver dauert 1:30 Minuten, und auf unserem Live-SQL-Server dauert 30 Sekunden; und in allen Fällen wird die CPU maximiert, während die größeren Joins ausgeführt werden.
Keine anderen Prozesse greifen gleichzeitig auf die Tabelle zu, und das kann angenommen werden.
Die Länge der Abfrage stört mich nicht so sehr wie die Nachfrage auf der CPU, die Probleme bei anderen Abfragen verursachen kann, die gleichzeitig versuchen, auf andere Datenbanken / Tabellen zuzugreifen.
Ich habe die Abfrage über den Abfrageoptimierer ausgeführt und alle Empfehlungen für Indizes und Statistiken befolgt.
Jede Hilfe, um diese Abfrage schneller oder zumindest weniger CPU-intensiv zu machen, wäre sehr willkommen. Wenn es in verschiedene Phasen unterteilt werden muss, ist das akzeptabel.
Um ehrlich zu sein, ist die Geschwindigkeit nicht so wichtig, da es sich um eine Massenoperation handelt, die auf einer Tabelle ausgeführt wird, die von anderen Prozessen nicht berührt wird.
Ich bin nicht besonders auf der Suche nach Kommentaren, wie schrecklich und un-normalisiert diese Struktur ist ... das weiß ich bereits: -)
Diese Seite ist für professionelle Programmierer, richtig.
Es ist verdächtig zu versuchen, an einer "Tabelle" ohne Primärschlüssel zu arbeiten. Gut, es ist ein Arbeitsbereich, keine echte Tabelle (aber es ist groß, und Sie versuchen, relationale Tabellenoperationen auszuführen). Gut, du weißt, dass es unnormalisiert ist. Tatsächlich ist die Datenbank nicht normalisiert, und diese "Tabelle" ist ein Produkt davon: ein exponentielles unnormalisiertes Produkt.
Das funktioniert und gibt mir ungefähr 413.000 Datensätze. Die Ergebnisse dieser Abfrage, die ich verwende, um eine andere Tabelle zu aktualisieren.
Das ist noch mehr verrückt. All dies (a) temporäre Arbeitstabellen und (b) temporäre Arbeitstabellen für das temporäre Arbeitstabellengeschäft sind klassische Symptome einer nicht normalisierten Datenbank. ODER Unfähigkeit, die Daten so zu verstehen, wie sie sind, wie Sie die Daten herausholen und unnötige Arbeitstabellen erstellen, um Ihren Bedarf zu decken. Ich versuche nicht, dich dazu zu bringen, das zu ändern, was die erste Option wäre, und die die Notwendigkeit für dieses ganze Durcheinander beseitigen würde.
Die zweite Option wäre, sehen Sie, ob Sie das Endergebnis aus den Originaltabellen erzeugen können, entweder:
- keine Arbeitstische verwenden
- Verwendung einer Arbeitsfläche
anstelle der beiden Arbeitstische (16.500 und 413.000 "Datensätze"; das sind zwei Ebenen der exponentiellen Entnormalisierung)
Die dritte Option ist, verbessere das Chaos, das du hast ... aber zuerst musst du verstehen, wo die Performance-Schweine sind ...
Aber die Abfrage funktioniert ziemlich schlecht, wie Sie es vielleicht bei so vielen Self-Joins erwarten würden
Nonsense, Joins und Self-Joins kosten nichts. Die Probleme sind, die Kosten sind in:
Sie arbeiten auf einem Heap
ohne PK
Wenn Sie in Joins Operatoren und Funktionen (statt pure "=") verwenden, bedeutet dies, dass der Server keine vernünftigen Entscheidungen über die Suchwerte treffen kann, so dass Sie die Tabelle immer scannen
Tabelle Größe (vielleicht anders auf Dev / Test / Prod)
gültige, verwendbare Indizes (oder nicht)
die Kosten sind in diesen vier Punkten, die Haufen sind in jeder Hinsicht brutal langsam, und die Operatoren identifizieren nichts, um die Suche einzuschränken; nicht die Tatsache, dass es eine Join-Operation gibt oder nicht.
Die nächste Serie von Problemen ist die Art, wie Sie es tun.
Weißt du NICHT, dass die "Joins" materialisierte Tabellen sind? Sie sind nicht "beitreten" Sie sind TABELLEN on the fly ??? Nichts ist frei: Materialisierung hat enorme Kosten. Sie konzentrieren sich so sehr darauf, zu materialisieren, ohne eine Vorstellung von den Kosten zu haben, dass Sie denken, dass die Joins das Problem sind. Warum das ?
Bevor Sie vernünftige Codierungsentscheidungen treffen können, müssen Sie SHOWPLAN und STATISTICS IO ON einstellen. Tun Sie dies, während Sie sich entwickeln (es ist noch lange nicht bereit zum "Testen"). Das wird dir eine Vorstellung von den Tischen geben; die Joins (was erwartet man gegen was es bestimmt, aus dem Chaos); die Arbeitstische (materialisiert). Die hohe CPU-Auslastung ist nichts, warten Sie, bis Sie die wahnsinnige I / O Ihres Codes sehen. Wenn Sie über die Kosten der Materialisierung im laufenden Betrieb streiten wollen, seien Sie mein Gast, aber schreiben Sie zuerst den SHOWPLAN.
Beachten Sie, dass die materialisierten -Tabellen keine Indizes haben, so dass die Tabelle jedes Mal nach sucht, um die "Joins".
Das Auswählen, wie es ist, macht Dutzende Male (vielleicht Hunderte) mehr Arbeit, als es braucht. Da der Tisch da ist und sich nicht bewegt hat, ist es eine sehr dumme Sache, eine andere Version davon zu materialisieren. Die wahre Frage ist also:
.
Falls Sie sich nicht sicher sind, bedeutet dies, dass die sechs materialisierten Tabellen eliminiert und durch reine Joins zur Haupttabelle ersetzt wird.
Wenn Sie es akzeptieren können, es aufzulösen, dann tun Sie es. Erstellen und laden Sie temporäre Tabellen, die diese Abfrage zuerst verwenden wird (dh 3 temporäre Tabellen nur für Aggregate). Stellen Sie sicher, dass Sie Indizes auf die richtigen Spalten setzen.
Also werden die 6 materialisierten Tabellen, die durch 3 ersetzt werden sollen, zu der Haupttabelle und 3 Verknüpfungen zu temporären aggregierten Tabellen hinzugefügt.
Irgendwo entlang der Linie haben Sie festgestellt, dass Sie kartesische Produkte und Duplikate haben; Anstatt die Ursache zu beheben (Code zu entwickeln, der die Menge produziert, die du benötigst), hast du das alles vermieden, es voller Duplikate belassen und die DISTINCT-Reihen herausgezogen. Das verursacht eine zusätzliche Arbeitstabelle. Repariere das. Sie müssen jede der temporären Tabellen (Arbeitstabellen, materialisierte Tabellen, was auch immer) zuerst korrigieren, bevor vernünftigerweise erwartet werden kann, dass die Auswahl, die sie verwendet, richtig ist.
DANN versuchen Sie die Auswahl.
Ich nehme an, dass alles in WebData läuft. Wenn nicht, setze IsGreaterThan () in diese db.
Bitte geben Sie DDL für UDF IsGreaterThan an. Wenn das Tabellen verwendet, müssen wir darüber wissen.
Bitte geben Sie die angeblichen Indizes mit der CREATE TABLE-Anweisung an. Sie könnten falsch oder schlechter sein, verdoppelt und nicht erforderlich.
Vergessen Sie die Identität oder erzwungene Werte, was ist die tatsächliche, echte, natürliche, logische PK für diesen Heap einer Arbeitstabelle?
Stellen Sie sicher, dass in den Join-Spalten kein Datentyp nicht übereinstimmt
Persönlich würde ich mich zu sehr dafür schämen, Code zu schreiben, wie Sie ihn haben. Es ist völlig unlesbar. Alles was ich getan habe, um die Probleme hier zu erkennen, ist es zu formatieren und lesbar zu machen. Es gibt Gründe dafür, den Code lesbar zu machen, so dass Sie Probleme schnell erkennen können. Es spielt keine Rolle, welche Formatierung Sie verwenden, aber Sie müssen formatieren, und Sie müssen es konsequent tun. Bitte bereinige es, bevor du es erneut posten kannst, zusammen mit ALLEN verwandten DDL.
Es ist kein Wunder, dass Sie keine Antworten bekommen haben. Sie müssen zuerst einige grundlegende Arbeiten ausführen (Showplan usw.) und den Code so vorbereiten, dass die Menschen ihn lesen können, damit er Antworten geben kann.
%Vor%Da Sie gesagt haben, dass Sie den Abfrageoptimierer bereits ausgeführt haben, kann ich nur davon ausgehen, dass alle Ihre Indizes korrekt sind. Mein nächster Ansatz ist das Join in der Anwendung. Was meine ich damit? Anstatt DB die Joins von 100 Tausend Zeilen zu machen. Holen Sie alle einmal in Ihrer Anwendung und dann Sie Schleifen und Logik, um zu tun, was Sie in SQL getan hätten statt.
Grund dafür ist, dass viele fe Anwendungen wie Facebook, Yahoo, AOL Stirnrunzeln verbindet. Joins sind nicht das Beste, wenn Sie nicht wissen, dass es schnell geht. In diesem Fall möchten Sie die Beitrittsanwendung speichern und für zukünftige Anforderungen zwischenspeichern.
Tags und Links sql sql-server performance tsql