1

Ich habe eine Datenbank in Produktion seit fast 3 Jahren, auf Sql 2008 (war '05, davor). aber es ist nicht sehr performant. Also bin ich Tweaking das Schema und Abfragen, um zu helfen, einige Dinge zu beschleunigen.Außerdem enthalten eine Punktzahl von Haupttabellen etwa 1-3 Mill Reihen, pro Tabelle (um ua Schätzung der Größen zu geben).Bitte erklären Sie mir, wenn ich mein DB-Schema aus Gründen der Leistung zerstöre :(

Hier ist ein Beispieldatenbank Diagramm (Soz unter NDA, so kann ich das Original nicht angezeigt): -

alt text http://img11.imageshack.us/img11/4608/dbschemaexample.png

Dinge zu beachten (die direkt auf meine pro verbunden sind blem): -

  • Ein Fahrzeug kann 0 (NULL) oder 1 Radio haben. (Linke äußere Verbindung)
  • Ein Fahrzeug kann 0 (NULL) oder 1 Cupholder (linke äußere Verbindung) haben
  • Ein Fahrzeug hat 1 Reifentyp (Inner Join).

Erstens sieht dies wie ein normalised database schema aus. Ich sauge und DB-Theorie, also ich vermute, das ist 3NF (mindestens) ... berühmte letzte Worte :)

Nun, dies ist meine Datenbank-Performance zu töten, weil diese beiden äußeren Joins und inneren Join aufgerufen werden ein viel Und es gibt auch ein paar mehr Joins in vielen Aussagen.

Um dies zu beheben, dachte ich, ich könnte versuchen und indizierte Sicht. Das Erstellen der Ansicht ist ein Kinderspiel. Aber es Indizierung funktioniert nicht -> kann nicht indizierte Sichten erstellen mit Verknüpfungen OR selbstbeziehende Tabellen (auch eine andere prob :()

Also, ich habe stundenlang geweint (und /wrists, dyed hair und wrote an emo song über. es und legt es auf myfailspace) und hat folgendes ...

  1. Added eine neue Zeile in jeden 'optional' Outer-Join-Tabellen (in diesem Beispiel Radios und Cupholder). ID = 0, Rest der Daten = 'Unknown Blah' oder 0's
  2. Elterntabellen aktualisieren, so dass alle NULL-Daten jetzt eine 0 haben
  3. Update relat Ionenschaft von äußeren Verbindungen zu inneren Verbindungen.

Jetzt funktioniert das. Ich kann sogar meine indizierte Sicht erstellen, die jetzt sehr schnell ist.

Also ... ich habe Schmerzen. Das widerspricht einfach allem, was ich gelernt habe. Ich fühle mich dreckig. Allein. Infiziert.

Ist das eine schlechte Sache zu tun? Ist das ein übliches Szenario der Denormalisierung einer Datenbank aus Gründen der Leistung?

würde ich einige Gedanken zu diesem lieben, bitte

PS :). Diese Bilder findet ein zufälliger Google - also nicht ich.

+0

Sie sagen, ein innerer Join ist schneller als ein äußerer Join? Es sollte nicht sein - kannst du ein Beispiel angeben, was langsam ist? –

+1

BTW: Sie haben Ihre Normalisierung nicht beeinflusst - es gibt viele Diskussionen über die Verwendung von Null in Tabellen und einige würden Ihre Änderung als eine Verbesserung sehen. –

+0

Welche Indizes haben Sie in Ihrer vorhandenen Vehikeltabelle? Ein Beispiel für eine langsame Abfrage wäre auch nützlich. – EvilRyry

Antwort

1

Datenbank sollte immer entworfen und zunächst in 3NF implementiert werden. Aber die Welt ist ein Ort der Realität, keine Ideale, und es ist okay, aus Leistungsgründen auf 2NF (oder sogar 1NF) zurückzugreifen. Mach dir nichts vor, Pragmatismus schlägt die Dogmatismus in der realen Welt die ganze Zeit.

Ihre Lösung, wenn es die Leistung verbessert, ist eine gute Lösung. Die Idee, ein echtes Radio (zum Beispiel) zu haben, das von niemandem hergestellt wird und keine Features hat, ist kein schlechtes - es wurde schon ein Lot gemacht, glaub mir :-) Der einzige Grund, warum du dieses Feld als NULL benutzen würdest war zu sehen, welche Fahrzeuge haben kein Radio und es gibt kaum einen Unterschied zwischen diesen Abfragen:

select Registration from vehicles where RadioId is null 
select Registration from vehicles where RadioId = 0 

Mein erster Gedanke war, einfach zu kombinieren die vier Tabellen in ein und hängen Sie die doppelte Datenproblem. Die meisten Probleme mit DBMS ergeben sich aus einer schlechten Leistung und nicht aus einem geringen Speicherplatz.

Vielleicht behalten Sie das als Ihre Fallback-Position, wenn Ihr aktuelles de-normalisiertes Schema auch langsam wird.

+1

Indem ich eine indizierte Sicht erstellt habe, habe ich alle 4 Tabellen zu einer zusammengefasst, während ich sie normalisierte (in meiner beklagenswerten db-Theorie). Um eine indizierte Sicht zu erstellen, musste ich alle inneren Verknüpfungen erstellen und habe daher ZERO-IDs anstelle von NULL-Werten. Du sagst also, das ist immer noch eine akzeptable Praxis, wenn auch nicht leicht üblich? –

+0

Es ist akzeptabel * und * häufiger als Sie denken. Datenbanken werden nicht entworfen, sondern in Ruhe gelassen und basierend auf den darin enthaltenen Daten kontinuierlich optimiert. Zum Beispiel sammeln wir Statistiken und, wenn nötig, erstellen wir unser Schema alle sechs Monate neu (obwohl es einige Jahre her ist, seit wir etwas ändern mussten, da sich die Art der Daten stabilisiert hat), um die Leistung zu halten hoch. – paxdiablo

+0

Und es ist ziemlich akzeptabel, einen "speziellen" Wert (in meinem Fall Id = 0) anstelle von Null zu verwenden, um äußere Joins durch innere Joins zu ersetzen? –

0

"... also bin ich dran, das Schema und die Abfragen zu optimieren, um einige Dinge zu beschleunigen ..." - Ich würde mich darüber streiten. Es scheint, dass Sie die Dinge verlangsamen. (Ich mache nur Spaß.)

Ich mag den Database Programmer Blog. Er hat zwei Spalten für und gegen die Normalisierung, die Sie nützlich finden könnten:

  1. http://database-programmer.blogspot.com/2008/10/argument-for-normalization.html
  2. http://database-programmer.blogspot.com/2008/10/argument-for-denormalization.html

Ich bin kein DBA, aber ich denke, die Beweise vor Ihren Augen ist: Die Leistung ist schlechter. Ich sehe nicht, wie man diese 1: 1-Beziehungen in einzelne Tabellen aufteilt, aber ich werde mich freuen, Anweisungen zu erhalten.

Bevor ich etwas änderte, würde ich SQL Server bitten, PLAN bei jeder Abfrage anzugeben, die langsam war, und diese Informationen verwenden, um genau zu sehen, was geändert werden sollte. Raten Sie nicht, weil ein Normalisierungsguru es Ihnen gesagt hat. Holen Sie sich die Daten, um zu sichern, was Sie tun. Was Sie tun, klingt wie Optimieren von Code der mittleren Ebene ohne Profiling. Darmgefühle sind nicht sehr genau.

+0

Ich habe den Abfrageplan fast visualisiert JEDES MAL, wenn ich meine Abfragen in SSMS ausführe. Mit den Joins zwischen zwei Tabellen würde ich 2 Millionen Zeilen bekommen, die sich einem weiteren massiven Betrag anschließen. Ich habe viele Indizes auch für die Eltern- und Kindtabellen. Es ist nur, dass es die beiden Tabellen verbinden muss, um Ergebnisse zu erhalten. Außerdem habe ich ot Tabellen aufgeteilt, nur die Beziehung und null Werte geändert. Und als ich die indizierten Ansichten ausführte, waren sie inadadwaayay schneller. –

2

Nullwerte werden im Allgemeinen nicht in Indizes verwendet. Sie haben einen Sentinel-Wert angegeben, sodass die Spalte immer einen Wert aufweist, der eine effizientere Verwendung Ihrer Indizes ermöglicht.

Sie haben auch nicht die Struktur Ihrer Datenbank geändert, daher würde ich diese Denormalisierung nicht nennen. Ich habe das mit Datumswerten gemacht, bei denen du ein "Enddatum" Null angegeben hast, das noch nicht beendet ist. Stattdessen habe ich es zu einem bekannten Datum in der Zukunft gemacht, das eine Indexierung ermöglichte.

Ich denke, das ist in Ordnung.

+0

Danke für den Kommentar. Sie sind zu 100% korrekt, dass ich nur von Nullen zu einem Sentinel-Wert gewechselt habe (noch nie zuvor gehört, dass das Wort so verwendet wurde). Ich fühle mich schmutzig und ich sehe, wie viele andere Leute das tun -> was du tust. Also ich bin nicht das allein, es scheint :) Ich dachte auch, NULLS hat keine Indizierung .. ?? –

+0

Nullen werden nicht indiziert, weil null! = Null, so dass es nicht notwendig ist, den Index zu betrachten, er ist schneller als ein Sentinel-Wert. –

0

Ich laufe in die gleiche Frage der Leistung vs akademische Exzellenz. Wir haben eine große Sicht auf eine Kundendatenbank mit 300 Spalten und 91000 Datensätzen. Wir verwenden Outer-Joins, um die Ansicht zu erstellen, und die Leistung ist ziemlich schlecht. Wir haben überlegt, zu inneren Joins zu wechseln, indem wir Dummy-Datensätze mit einem Wert von Null für die Spalten, an denen wir uns anschließen, einfügen (statt null), um einen eindeutigen Index für die Ansicht zu aktivieren.

Ich muss zustimmen, dass, wenn Leistung wichtig ist, manchmal seltsame Dinge getan werden müssen, um es zu ermöglichen. Letztendlich ist es denen, die unsere Rechnungen bezahlen, egal, ob die Architektur perfekt ist.

Verwandte Themen