Bei der Skalierbarkeit geht es darum, die wiederholte Arbeit vorab zu berechnen, zu verteilen oder auf das Wesentliche zu reduzieren, um den Ressourcenverbrauch pro Arbeitseinheit zu minimieren. Um gut zu skalieren, tun Sie nichts, was Sie in Bezug auf die Lautstärke nicht benötigen, und die Dinge, die Sie tatsächlich tun, stellen Sie sicher, dass sie so effizient wie möglich ausgeführt werden.
In diesem Zusammenhang ist das Verbinden zweier separater Datenquellen natürlich relativ langsam, zumindest im Vergleich zum Nicht-Verbinden, da Sie diese Arbeit live an dem Punkt erledigen müssen, an dem der Benutzer sie anfordert.
Denken Sie jedoch daran, dass die Alternative darin besteht, überhaupt keine zwei separaten Daten mehr zu haben. Sie müssen die beiden unterschiedlichen Datenpunkte in denselben Datensatz einfügen. Sie können nicht zwei verschiedene Daten ohne Konsequenz irgendwo kombinieren, stellen Sie also sicher, dass Sie den Kompromiss verstehen.
Die gute Nachricht ist, dass moderne relationale Datenbanken gut in Joins sind. Sie sollten sich Joins mit einer guten Datenbank, die gut verwendet wird, nicht so langsam vorstellen. Es gibt eine Reihe von skalierbarkeitsfreundlichen Möglichkeiten, um rohe Verknüpfungen zu erstellen und sie viel schneller zu machen:
- Verbinden Sie sich mit einem Ersatzschlüssel (Autonumer / Identity-Spalte) anstelle eines natürlichen Schlüssels. Dies bedeutet kleinere (und daher schnellere) Vergleiche während der Verknüpfungsoperation
- Indizes
- Materialisierte / indizierte Ansichten (stellen Sie sich dies als vorberechneten Join oder verwaltete De-Normalisierung vor)
- Berechnete Spalten. Sie können dies verwenden, um die Schlüsselspalten eines Joins zu hashen oder auf andere Weise vorab zu berechnen, sodass ein komplizierter Vergleich für einen Join jetzt viel kleiner und möglicherweise vorindiziert ist.
- Tabellenpartitionen (hilft bei großen Datenmengen, indem die Last auf mehrere Festplatten verteilt wird oder wenn ein Tabellenscan auf einen Partitionsscan beschränkt wird)
- OLAP (berechnet die Ergebnisse bestimmter Arten von Abfragen / Verknüpfungen vor. Es ist nicht ganz richtig, aber Sie können sich dies als generische Denormalisierung vorstellen.)
- Replikation, Verfügbarkeitsgruppen, Protokollversand oder andere Mechanismen, mit denen mehrere Server Leseanfragen für dieselbe Datenbank beantworten und so Ihre Arbeitslast auf mehrere Server verteilen können.
- Verwendung einer Caching-Ebene wie Redis, um zu vermeiden, dass Abfragen erneut ausgeführt werden, für die komplexe Verknüpfungen erforderlich sind.
Ich würde sogar sagen, dass der Hauptgrund, warum relationale Datenbanken überhaupt existieren, darin besteht, dass Sie Joins effizient durchführen können * . Es geht sicherlich nicht nur darum, strukturierte Daten zu speichern (das können Sie mit Flatfile-Konstrukten wie CSV oder XML tun). Mit einigen der von mir aufgelisteten Optionen können Sie Ihren Join sogar im Voraus vollständig erstellen, sodass die Ergebnisse bereits vor der Ausgabe der Abfrage erstellt werden - als hätten Sie die Daten denormalisiert (zugegebenermaßen auf Kosten langsamerer Schreibvorgänge).
Wenn Sie einen langsamen Join haben, verwenden Sie Ihre Datenbank wahrscheinlich nicht richtig.
Eine De-Normalisierung sollte erst durchgeführt werden, nachdem diese anderen Techniken fehlgeschlagen sind. Und die einzige Möglichkeit, "Misserfolg" wirklich zu beurteilen, besteht darin, sinnvolle Leistungsziele festzulegen und an diesen Zielen zu messen. Wenn Sie nicht gemessen haben, ist es zu früh, um überhaupt an eine De-Normalisierung zu denken.
* Das heißt, existieren als Entitäten, die sich von bloßen Sammlungen von Tabellen unterscheiden. Ein weiterer Grund für eine echte rdbms ist der sichere gleichzeitige Zugriff.
Verknüpfungen können langsamer sein als das Vermeiden durch De-Normalisierung, aber bei korrekter Verwendung (Verbinden von Spalten mit geeigneten Indizes usw.) sind sie nicht von Natur aus langsam .
Die De-Normalisierung ist eine von vielen Optimierungstechniken, die Sie in Betracht ziehen können, wenn Ihr gut gestaltetes Datenbankschema Leistungsprobleme aufweist.
quelle
Artikel sagt, dass sie im Vergleich zum Fehlen von Verknüpfungen langsam sind. Dies kann durch Denormalisierung erreicht werden. Es gibt also einen Kompromiss zwischen Geschwindigkeit und Normalisierung. Vergessen Sie auch nicht die vorzeitige Optimierung :)
quelle
Zuallererst besteht die Existenzberechtigung einer relationalen Datenbank darin, Beziehungen zwischen Entitäten modellieren zu können. Verknüpfungen sind einfach die Mechanismen, mit denen wir diese Beziehungen durchlaufen. Sie sind sicherlich mit nominalen Kosten verbunden, aber ohne Joins gibt es wirklich keinen Grund, eine relationale Datenbank zu haben.
In der akademischen Welt lernen wir Dinge wie die verschiedenen normalen Formen (1., 2., 3., Boyce-Codd usw.) und wir lernen verschiedene Arten von Schlüsseln (primär, fremd, alternativ, einzigartig usw.) und wie Diese Dinge passen zusammen, um eine Datenbank zu entwerfen. Und wir lernen die Grundlagen von SQL sowie die Manipulation von Struktur und Daten (DDL & DML).
In der Unternehmenswelt erweisen sich viele der akademischen Konstrukte als wesentlich weniger lebensfähig, als wir angenommen hatten. Ein perfektes Beispiel ist der Begriff eines Primärschlüssels. Akademisch gesehen ist es dieses Attribut (oder diese Sammlung von Attributen), das eine Zeile in der Tabelle eindeutig identifiziert. In vielen Problembereichen besteht der richtige akademische Primärschlüssel aus 3 oder 4 Attributen. Fast jeder in der modernen Unternehmenswelt verwendet jedoch eine automatisch generierte, sequentielle Ganzzahl als Primärschlüssel einer Tabelle. Warum? Zwei Gründe. Das erste ist, weil es das Modell viel sauberer macht, wenn Sie FKs überall migrieren. Die zweite und wichtigste Frage zu dieser Frage ist, dass das Abrufen von Daten über Joins mit einer einzelnen Ganzzahl schneller und effizienter ist als mit 4 Varchar-Spalten (wie bereits von einigen Leuten erwähnt).
Lassen Sie uns nun etwas tiefer in zwei spezifische Subtypen realer Datenbanken eintauchen. Der erste Typ ist eine Transaktionsdatenbank. Dies ist die Grundlage für viele E-Commerce- oder Content-Management-Anwendungen, die moderne Websites antreiben. Mit einer Transaktions-DB optimieren Sie stark in Richtung "Transaktionsdurchsatz". Die meisten Commerce- oder Content-Apps müssen die Abfrageleistung (von bestimmten Tabellen) mit der Einfügeleistung (in anderen Tabellen) in Einklang bringen, obwohl jede App ihre eigenen geschäftlichen Probleme hat, die gelöst werden müssen.
Der zweite Typ einer realen Datenbank ist eine Berichtsdatenbank. Diese werden fast ausschließlich zur Aggregation von Geschäftsdaten und zur Erstellung aussagekräftiger Geschäftsberichte verwendet. Sie sind in der Regel anders geformt als die Transaktionsdatenbanken, in denen die Daten generiert werden, und sie sind in hohem Maße für die Geschwindigkeit des Ladens von Massendaten (ETLs) und die Abfrageleistung bei großen oder komplexen Datenmengen optimiert.
In jedem Fall muss der Entwickler oder DBA sowohl die Funktions- als auch die Leistungskurven sorgfältig abwägen, und auf beiden Seiten der Gleichung gibt es viele Tricks zur Leistungssteigerung. In Oracle können Sie einen sogenannten "Erklärungsplan" ausführen, um genau zu sehen, wie eine Abfrage analysiert und ausgeführt wird. Sie möchten die ordnungsgemäße Verwendung von Indizes durch die DB maximieren. Ein wirklich unangenehmes Nein-Nein ist das Einfügen einer Funktion in die where-Klausel einer Abfrage. Wenn Sie dies tun, stellen Sie sicher, dass Oracle keine Indizes für diese bestimmte Spalte verwendet und dass im EXPLAIN-Plan wahrscheinlich ein vollständiger oder teilweiser Tabellenscan angezeigt wird. Dies ist nur ein konkretes Beispiel dafür, wie eine Abfrage geschrieben werden kann, die langsam ist und nichts mit Joins zu tun hat.
Und während es sich um Tabellenscans handelt, wirken sie sich offensichtlich proportional zur Größe der Tabelle auf die Abfragegeschwindigkeit aus. Ein vollständiger Tabellenscan von 100 Zeilen ist nicht einmal erkennbar. Führen Sie dieselbe Abfrage für eine Tabelle mit 100 Millionen Zeilen aus, und Sie müssen nächste Woche zur Rückgabe zurückkehren.
Lassen Sie uns eine Minute über Normalisierung sprechen. Dies ist ein weiteres weitgehend positives akademisches Thema, das überstrapaziert werden kann. Wenn wir über Normalisierung sprechen, meinen wir meistens die Beseitigung doppelter Daten, indem wir sie in eine eigene Tabelle einfügen und eine FK migrieren. Die Leute überspringen normalerweise die gesamte Abhängigkeitssache, die von 2NF und 3NF beschrieben wird. Und doch ist es im Extremfall durchaus möglich, eine perfekte BCNF-Datenbank zu haben, die riesig ist und gegen die man Code schreiben kann, weil sie so normalisiert ist.
Wo balancieren wir also? Es gibt keine einzige beste Antwort. Alle besseren Antworten sind in der Regel Kompromisse zwischen der einfachen Strukturpflege, der einfachen Datenpflege und der einfachen Codeerstellung / -pflege. Im Allgemeinen ist es umso besser, je weniger Daten doppelt vorhanden sind.
Warum sind Joins manchmal langsam? Manchmal ist es schlechtes relationales Design. Manchmal ist die Indizierung ineffektiv. Manchmal ist es ein Problem mit dem Datenvolumen. Manchmal ist es eine schrecklich geschriebene Anfrage.
Es tut mir leid für diese langwierige Antwort, aber ich fühlte mich gezwungen, einen fleischigeren Kontext für meine Kommentare bereitzustellen, anstatt nur eine 4-Punkte-Antwort abzurasseln.
quelle
Menschen mit Datenbanken mit Terrabyte-Größe verwenden immer noch Verknüpfungen. Wenn sie sie dazu bringen können, leistungsmäßig zu arbeiten, können Sie dies auch.
Es gibt viele Gründe, nicht zu denomalisieren. Erstens ist die Geschwindigkeit ausgewählter Abfragen nicht das einzige oder sogar Hauptproblem bei Datenbanken. Die Integrität der Daten ist das erste Anliegen. Wenn Sie denormalisieren, müssen Sie Techniken einsetzen, um die Daten denormalisiert zu halten, wenn sich die übergeordneten Daten ändern. Angenommen, Sie speichern den Clientnamen in allen Tabellen, anstatt sich mit der Clienttabelle auf der client_Id zu verbinden. Wenn sich nun der Name des Clients ändert (100% ige Wahrscheinlichkeit, dass sich einige Namen von Clients im Laufe der Zeit ändern), müssen Sie jetzt alle untergeordneten Datensätze aktualisieren, um diese Änderung widerzuspiegeln. Wenn Sie dies in einem Kaskaden-Update tun und über eine Million untergeordneter Datensätze verfügen, wie schnell wird dies voraussichtlich sein und wie viele Benutzer werden währenddessen unter Sperrproblemen und Verzögerungen bei ihrer Arbeit leiden? Weiter die meisten Leute, die denormalisieren, weil "
Die Denormalisierung ist ein komplexer Prozess, der ein gründliches Verständnis der Datenbankleistung und -integrität erfordert, wenn er korrekt durchgeführt werden soll. Versuchen Sie nicht zu denormalisieren, es sei denn, Sie verfügen über ein solches Fachwissen im Personal.
Joins sind ziemlich schnell genug, wenn Sie mehrere Dinge tun. Verwenden Sie zuerst einen Suggorgate-Schlüssel. Ein Int-Join ist fast immer der schnellste Join. Zweitens indizieren Sie immer den Fremdschlüssel. Verwenden Sie abgeleitete Tabellen oder Verknüpfungsbedingungen, um ein kleineres Dataset zum Filtern zu erstellen. Wenn Sie über eine große, sehr komplexe Datenbank verfügen, sollten Sie eine professionelle Datenbankperson mit Erfahrung in der Partitionierung und Verwaltung großer Datenbanken einstellen. Es gibt viele Techniken, um die Leistung zu verbessern, ohne Verknüpfungen zu entfernen.
Wenn Sie nur Abfragefunktionen benötigen, können Sie ein Datawarehouse entwerfen, das denormalisiert werden kann und über ein ETL-Tool (auf Geschwindigkeit optimiert) und nicht über die Eingabe von Benutzerdaten gefüllt wird.
quelle
Joins sind langsam, wenn
Je größer Ihre Datenmengen sind, desto mehr Verarbeitung benötigen Sie für eine Abfrage. Wenn Sie jedoch die ersten drei der oben genannten Optionen überprüfen und bearbeiten, erhalten Sie häufig hervorragende Ergebnisse.
Ihre Quelle gibt eine Denormalisierung als Option an. Dies ist nur in Ordnung, solange Sie bessere Alternativen ausgeschöpft haben.
quelle
Die Verknüpfungen können langsam sein, wenn große Teile von Datensätzen von jeder Seite gescannt werden müssen.
So was:
Selbst wenn ein Index für definiert ist
account_customer
, müssen alle Datensätze von letzterem noch gescannt werden.Für die Abfrageliste berücksichtigen die anständigen Optimierer wahrscheinlich nicht einmal den Indexzugriffspfad, sondern führen stattdessen ein
HASH JOIN
oder einMERGE JOIN
.Beachten Sie, dass für eine Abfrage wie diese:
Der Join wird höchstwahrscheinlich schnell sein: Zuerst wird ein Index on
customer_last_name
verwendet, um alle Stellphlug's zu filtern (die natürlich nicht sehr zahlreich sind), dannaccount_customer
wird für jeden Stellphlug ein Index-Scan on ausgegeben, um seine Transaktionen zu finden.Trotz der Tatsache, dass dies Milliarden von Datensätzen sein können
accounts
undcustomers
nur wenige tatsächlich gescannt werden müssen.quelle
accounts(account_customer)
meisten RDBMS ein Index definiert ist , wird dieser Index verwendet, um genau herauszufinden, welche Zeilen dercustomers
Datenbank gescannt werden müssen.HASH JOIN
wäre viel schneller, so dass es verwendet wird, außer in allen wichtigen Datenbanken, außerMySQL
dass nurcustomers
in einer verschachtelten Schleife geführt wird (da es kleiner ist)Joins are fast.
Verknüpfungen sollten als Standardpraxis mit einem ordnungsgemäß normalisierten Datenbankschema betrachtet werden. Mit Verknüpfungen können Sie unterschiedliche Datengruppen auf sinnvolle Weise verbinden. Fürchte dich nicht vor dem Beitritt.Die Einschränkung besteht darin, dass Sie die Normalisierung, das Verknüpfen und die ordnungsgemäße Verwendung von Indizes verstehen müssen.
Vorsicht vor vorzeitiger Optimierung, da der Fehler Nummer eins aller Entwicklungsprojekte die Frist einhält. Sobald Sie das Projekt abgeschlossen haben und die Kompromisse verstanden haben, können Sie die Regeln brechen, wenn Sie dies rechtfertigen können.
Es ist richtig, dass sich die Join-Leistung nicht linear verschlechtert, wenn die Größe des Datensatzes zunimmt. Daher lässt es sich nicht so gut skalieren wie einzelne Tabellenabfragen, aber es skaliert trotzdem.
Es ist auch wahr, dass ein Vogel ohne Flügel schneller fliegt, aber nur direkt nach unten.
quelle
Joins erfordern zusätzliche Verarbeitung, da sie mehr Dateien und Indizes suchen müssen, um die Daten miteinander zu "verbinden". "Sehr große Datenmengen" sind jedoch alle relativ. Was ist die Definition von groß? Im Fall von JOINs denke ich, dass dies ein Verweis auf eine große Ergebnismenge ist, nicht auf diesen Gesamtdatensatz.
Die meisten Datenbanken können sehr schnell eine Abfrage verarbeiten, bei der 5 Datensätze aus einer Primärtabelle ausgewählt und für jeden Datensatz 5 Datensätze aus einer zugehörigen Tabelle verknüpft werden (vorausgesetzt, die richtigen Indizes sind vorhanden). Diese Tabellen können jeweils Hunderte Millionen Datensätze oder sogar Milliarden enthalten.
Sobald Ihre Ergebnismenge wächst, werden sich die Dinge verlangsamen. Wenn die Primärtabelle im selben Beispiel 100.000 Datensätze ergibt, müssen 500.000 "verbundene" Datensätze gefunden werden. Ziehen Sie einfach so viele Daten mit zusätzlichen Verzögerungen aus der Datenbank.
Vermeiden Sie JOINs nicht, sondern wissen Sie nur, dass Sie möglicherweise optimieren / denormalisieren müssen, wenn Datasets "sehr groß" werden.
quelle
Auch aus dem Artikel, den Sie zitiert haben:
und
und
Der Artikel diskutiert Mega-Sites wie Ebay. Bei dieser Nutzungsstufe müssen Sie wahrscheinlich etwas anderes als die einfache relationale Vanilla-Datenbankverwaltung in Betracht ziehen. Aber im "normalen" Geschäftsverlauf (Anwendungen mit Tausenden von Benutzern und Millionen von Datensätzen) sind diese teureren, fehleranfälligeren Ansätze übertrieben.
quelle
Verknüpfungen werden als Gegenkraft zur Skalierbarkeit angesehen, da sie normalerweise den Engpass darstellen und nicht einfach verteilt oder parallel geschaltet werden können.
quelle
Richtig gestaltete Tabellen mit den richtigen Angaben und korrekt geschriebenen Abfragen sind nicht immer langsam. Wo immer du das gehört hast:
hat keine Ahnung wovon sie reden !!! Die meisten Joins werden sehr schnell sein. Wenn Sie viele, viele Zeilen gleichzeitig verbinden müssen, können Sie im Vergleich zu einer denormalisierten Tabelle einen Treffer erzielen. Dies geht jedoch auf ordnungsgemäß gestaltete Tabellen zurück. Sie müssen wissen, wann Sie denormalisieren müssen und wann nicht. Teilen Sie in einem umfangreichen Berichtssystem die Daten in denormalisierten Tabellen für Berichte auf oder erstellen Sie sogar ein Data Warehouse. In einem transaktionslastigen System normalisieren Sie die Tabellen.
quelle
Die Menge der temporären Daten, die generiert werden, kann basierend auf den Verknüpfungen sehr groß sein.
Zum Beispiel hatte eine Datenbank hier bei der Arbeit eine generische Suchfunktion, bei der alle Felder optional waren. Die Suchroutine hat vor Beginn der Suche eine Verknüpfung für jede Tabelle durchgeführt. Das hat am Anfang gut funktioniert. Aber jetzt, wo die Haupttabelle über 10 Millionen Zeilen hat ... nicht so sehr. Die Suche dauert jetzt 30 Minuten oder länger.
Ich wurde beauftragt, die gespeicherte Suchprozedur zu optimieren.
Das erste, was ich tat, war, wenn eines der Felder der Haupttabelle durchsucht wurde, eine Auswahl für eine temporäre Tabelle nur für diese Felder vorzunehmen. DANN habe ich alle Tabellen mit dieser temporären Tabelle verbunden, bevor ich den Rest der Suche durchgeführt habe. Suchen, bei denen eines der Haupttabellenfelder jetzt weniger als 10 Sekunden dauert.
Wenn keines der Haupttabellenfelder durchsucht wird, mache ich ähnliche Optimierungen für andere Tabellen. Wenn ich fertig war, dauert keine Suche länger als 30 Sekunden, wobei die meisten unter 10 sind.
Die CPU-Auslastung des SQL-Servers ging ebenfalls stark zurück.
quelle
Während Verknüpfungen (vermutlich aufgrund eines normalisierten Designs) beim Abrufen von Daten offensichtlich langsamer sein können als das Lesen aus einer einzelnen Tabelle, kann eine denormalisierte Datenbank für Datenerstellungs- / Aktualisierungsvorgänge langsam sein, da der Platzbedarf der gesamten Transaktion nicht minimal ist.
In einer normalisierten Datenbank befinden sich Daten nur an einem Ort, sodass der Platzbedarf für ein Update so gering wie möglich ist. In einer denormalisierten Datenbank ist es möglich, dass dieselbe Spalte in mehreren Zeilen oder über Tabellen hinweg aktualisiert werden muss, was bedeutet, dass der Platzbedarf größer ist und die Wahrscheinlichkeit von Sperren und Deadlocks zunimmt.
quelle
Ja, die Auswahl von Zeilen aus einer denormalisierten Tabelle (unter der Annahme anständiger Indizes für Ihre Abfrage) ist möglicherweise schneller als die Auswahl von Zeilen, die aus der Verknüpfung mehrerer Tabellen erstellt wurden, insbesondere wenn für die Verknüpfungen keine effizienten Indizes verfügbar sind.
Die im Artikel genannten Beispiele - Flickr und eBay - sind IMO-Ausnahmefälle und haben (und verdienen) außergewöhnliche Antworten. Der Autor weist ausdrücklich auf das Fehlen von RI und das Ausmaß der Datenvervielfältigung im Artikel hin.
Die meisten Anwendungen - wiederum IMO - profitieren von der Validierung und reduzierten Duplizierung durch RDBMS.
quelle
Sie können langsam sein, wenn sie schlampig gemacht werden. Wenn Sie beispielsweise bei einem Join ein 'select *' ausführen, dauert es wahrscheinlich eine Weile, bis Sie die Daten zurückbekommen. Wenn Sie jedoch sorgfältig auswählen, welche Spalten aus jeder Tabelle zurückgegeben werden sollen, und die richtigen Indizes vorhanden sind, sollte dies kein Problem darstellen.
quelle