Was ist Performance-Mäßig besser?

Status
Nicht offen für weitere Antworten.
Hallo,

folgendes szenario:
Ich schreibe ein Web-Communityskript und benutzte eine MySql-Datenbank.
In der DB gibt es eine Tabelle "Mitglieder". Dort sind für alle mitglieder neben benutzername und passwort noch eine Menge anderer Daten gespeichert, von Namen und Adresse über Hobbys bis Lieblingsmusik. Insgesamt ca. 50 felder.
Wäre es sinnvoll diese Tabelle in mehrere Tabellen aufzuspalten?

Wenn ich jetzt auf einer Seite einen Aufruf "Select Benutzer_ID From Mitglieder where...." mache, läd dann mein DBS erstmal die ganze riesen Mitgliedertabelle und pickt dann raus was gebraucht wird? In dem Fall wäre es ja aufjedenfall besser die tabelle zu splitten.

Hatte zwar mal ne DBS vorlesung, weiß da aber leider nicht mehr so genau bescheid und bevor ich was unglaublich ressourcenfressendes programmiere frag ich lieber mal nach ;-)


Danke für eure Hilfe
P.C.

PS: Ich meine mit Splitten nicht, dass ich die ersten x rows in eine tabelle packe und die nächsten in ne andere, sondern splitten indem ich z.B. in einer Tabelle nur username und passwort speichere, in eine andere namen und adressen, in eine andere hobbies und interessen, etc. obwohl das von den Normalformen her eigentlich nicht nötig wäre.
 
Zuletzt bearbeitet:

Empire Phoenix

Top Contributor
Keine Sorge, die DBServer jegliche mir bekannten Datenbank sollten intelligent genug sein das selber effizient zu managen (das ist ja einer der Hauptgründe die zu benutzen), zumindest war bei privaten Anwendung gleich welcher Art der DB server bislang immer das kleinste Problem
 

MrWhite

Bekanntes Mitglied
Ich möchte zu dieser Fragestellung gerne auf folgenden Link verweisen: When and why are database joins expensive? - Stack Overflow

Besser und prägnanter habe ich es bisher noch nirgends gelesen. Mit bestem Dank an David Aldridge.

Denormalising to improve performance? It sounds convincing, but it doesn't hold water.

Chris Date, which advanced the relational data model along with Dr Ted Codd, its creator, got tired of misinformed arguments against normalisation and systematically demolished them using scientific method - he got large databases and tested these assertions. I think he wrote it up in Relational Database Writings 1988-1991 but this book was later rolled into edition six of Introduction to Database Systems. This is the definitive text on database theory and design, currently in its eighth edition. Chris Date was an expert in this field when most of us were still running around barefoot.

He found that:

* Some of them hold for special cases
* All of them fail to pay off for general use
* All of them are significantly worse for other special cases

It all comes back to mitigating the size of the working set. Joins involving properly selected keys with correctly set up indexes are cheap, not expensive, because they allow significant pruning of the result before the rows are materialised.

Materialising the result involves bulk disk reads which are the most expensive aspect of the exercise by an order of magnitude. Performing a join, by contrast, logically requires retrieval of only the keys. In practice, not even the key values are fetched: the key hash values are used for join comparisons, mitigating the cost of multi-column joins and radically reducing the cost of joins involving string comparisons. Not only will vastly more fit in cache, there's a lot less disk reading to do.

Moreover, a good optimiser will choose the most restrictive condition and apply it before it performs a join, very effectively leveraging the high selectivity of joins on indexes with high cardinality.

Admittedly this type of optimisation can also be applied to denormalised databases, but the sort of people who want to denormalise a schema typically don't think about cardinality when (if) they set up indexes.

It is important to understand that table scans (examination of every row in a table in the course of producing a join) are rare in practice. A query optimiser will choose a table scan only when one or more of the following holds.

* There are fewer than 200 rows in the relation (in this case a scan will be cheaper)
* There are no suitable indexes on the join columns (if it's meaningful to join on these columns then why aren't they indexed? fix it)
* A type coercion is required before the columns can be compared (WTF?! fix it or go home)
* One of the arguments of the comparison is an expression (no index)

Performing an operation is more expensive than not performing it. However, performing the wrong operation, being forced into pointless disk I/O and then discarding the dross prior to performing the join you really need, is much more expensive. Even when the "wrong" operation is precomputed and indexes have been sensibly applied, there remains significant penalty. Denormalising to precompute a join - notwithstanding the update anomalies entailed - is a commitment to a particular join. If you need a different join, that commitment is going to cost you big.

If anyone wants to remind me that it's a changing world, I think you'll find that bigger datasets on gruntier hardware just exaggerates the spread of Date's findings.

For all of you who work on billing systems or junk mail generators (shame on you) and are indignantly setting hand to keyboard to tell me that you know for a fact that denormalisation is faster, sorry but you're living in one of the special cases - specifically, the case where you process all of the data, in-order. It's not a general case, and you are justified in your strategy.

You are not justified in falsely generalising it. See the end of the notes section for more information on appropriate use of denormalisation in data warehousing scenarios.

I'd also like to respond to

Joins are just cartesian products with some lipgloss

What a load of bollocks. Restrictions are applied as early as possible, most restrictive first. You've read the theory, but you haven't understood it. Joins are treated as cartesian products to which predicates apply only by the query optimiser. This is a symbolic representation (a normalisation, in fact) to facilitate symbolic decomposition so the optimiser can produce all the equivalent transformations and rank them by cost and selectivity so that it can select the best query plan.

The only way you will ever get the optimiser to produce a cartesian product is to fail to supply a predicate: SELECT * FROM A,B

Notes

David Aldridge provides some important additional information.

There is indeed a variety of other strategies besides indexes and table scans, and a modern optimiser will cost them all before producing an execution plan.

A practical piece of advice: if it can be used as a foreign key then index it, so that an index strategy is available to the optimiser.

I used to be smarter than the MSSQL optimiser. That changed two versions ago. Now it generally teaches me. It is, in a very real sense, an expert system, codifying all the wisdom of many very clever people in a domain sufficiently closed that a rule-based system is effective.

"Bollocks" may have been tactless. I am asked to be less haughty and reminded that math doesn't lie. This is true, but not all of the implications of mathematical models should necessarily be taken literally. Square roots of negative numbers are very handy if you carefully avoid examining their absurdity (pun there) and make damn sure you cancel them all out before you try to interpret your equation.

The reason that I responded so savagely was that the statement as worded says that

Joins are cartesian products...

This may not be what was meant but it is what was written, and it's categorically untrue. A cartesian product is a relation. A join is a function. More specifically, a join is a relation-valued function. With an empty predicate it will produce a cartesian product, and checking that it does so is one correctness check for a database query engine, but nobody writes unconstrained joins in practice because they have no practical value outside a classroom.

I called this out because I don't want readers falling into the ancient trap of confusing the model with the thing modelled. A model is an approximation, deliberately simplified for convenient manipulation.

The cut-off for selection of a table-scan join strategy may vary between database engines. It is affected by a number of implementation decisions such as tree-node fill-factor, key-value size and subtleties of algorithm, but broadly speaking high-performance indexing has an execution time of k log n + c. The C term is a fixed overhead mostly made of setup time, and the shape of the curve means you don't get a payoff (compared to a linear search) until n is in the hundreds.

Sometimes denormalisation is a good idea

Denormalisation is a commitment to a particular join strategy. As mentioned earlier, this interferes with other join strategies. But if you have buckets of disk space, predictable patterns of access, and a tendency to process much or all of it, then precomputing a join can be very worthwhile.

You can also figure out the access paths your operation typically uses and precompute all the joins for those access paths. This is the premise behind data warehouses, or at least it is when they're built by people who know why they're doing what they're doing, and not just for the sake of buzzword compliance.

A properly designed data warehouse is produced periodically by a bulk transformation out of a normalised transaction processing system. This separation of the operations and reporting databases has the very desirable effect of eliminating the clash between OLTP and OLAP (online transaction processing ie data entry, and online analytical processing ie reporting).

An important point here is that apart from the periodic updates, the data warehouse is read only. This renders moot the question of update anomalies.

Don't make the mistake of denormalising your OLTP database (the database on which data entry happens). It might be faster for billing runs but if you do that you will get update anomalies. Ever tried to get Reader's Digest to stop sending you stuff?

Disk space is cheap these days, so knock yourself out. But denormalising is only part of the story for data warehouses. Much bigger performance gains are derived from precomputed rolled-up values: monthly totals, that sort of thing. It's always about reducing the working set.

Notes

David Aldridge provides some important additional information.

There is indeed a variety of other strategies besides indexes and table scans, and a modern optimiser will cost them all before producing an execution plan.

A practical piece of advice: if it can be used as a foreign key then index it, so that an index strategy is available to the optimiser.

I used to be smarter than the MSSQL optimiser. That changed two versions ago. Now it generally teaches me. It is, in a very real sense, an expert system, codifying all the wisdom of many very clever people in a domain sufficiently closed that a rule-based system is effective.

"Bollocks" may have been tactless. I am asked to be less haughty and reminded that math doesn't lie. This is true, but not all of the implications of mathematical models should necessarily be taken literally. Square roots of negative numbers are very handy if you carefully avoid examining their absurdity (pun there) and make damn sure you cancel them all out before you try to interpret your equation.

The reason that I responded so savagely was that the statement as worded says that

Joins are cartesian products...

This may not be what was meant but it is what was written, and it's categorically untrue. A cartesian product is a relation. A join is a function. More specifically, a join is a relation-valued function. With an empty predicate it will produce a cartesian product, and checking that it does so is one correctness check for a database query engine, but nobody writes unconstrained joins in practice because they have no practical value outside a classroom.

I called this out because I don't want readers falling into the ancient trap of confusing the model with the thing modelled. A model is an approximation, deliberately simplified for convenient manipulation.

The cut-off for selection of a table-scan join strategy may vary between database engines. It is affected by a number of implementation decisions such as tree-node fill-factor, key-value size and subtleties of algorithm, but broadly speaking high-performance indexing has an execution time of k log n + c. The C term is a fixed overhead mostly made of setup time, and the shape of the curve means you don't get a payoff (compared to a linear search) until n is in the hundreds.
 

ice-breaker

Top Contributor
Als Randbemerkung noch: Es gibt in Datenbanken noch weit mehr Performanzindikatoren als Joins: Views, Subselects, Gruppen-Operationen (GROUP BY), schlechte Indizes, zu große Tabellen, MyIsam, Trigger viele Punkte können eine schlechte Performance bewirken, aus dem Grunde ist es das Beste, die Datenbank sinnvoll über ORM zu kapseln, denn den einen oder anderen Fehler wirst du sicherlich machen, es ist nur eben die Frage, wie leicht man diese nachher wieder beheben kann ;)

Und ja soviele Attribute in einer MySQL-Tabelle sind wirklich negativ ;) Denn das Caching von MySQL (InnoDB) setzt du damit unter eine Bewährungsprobe, die Caches sind per Default relativ klein eingestellt, wenn nun jeweils einen so großer Datensatz darin gespeichert wird, müssen andere Daten wieder rausgeräumt werden, es finden viele Cache-Misses statt.

Wer sich für das Thema (im speziellen MySQL) wirklich interessiert, dem kann ich die 1. und 2. Auflage des High Performance MySQL Buches aus dem O'Reilly-Verlag nahe legen. Es wird wirklich ein sehr großer Teil abgedeckt was man wissen kann, natürlich nicht alles, aber speziell in der 2. Auflage wird darauf eingegangen wie eine DB funktioniert, was essentiell ist, um Optimierungen durchführen zu können.
 
Zuletzt bearbeitet:
G

Gast2

Gast
ich finde die Dokumentation von MySQL zum Thema Optimierung schon recht ausführlich
 
@mogel: Über die normalformen weiß ich schon bescheid. Hilft mir bei meinem Problem aber nicht weiter, denn meine Riesentabelle ist ja in BCNF.

Und ja soviele Attribute in einer MySQL-Tabelle sind wirklich negativ Denn das Caching von MySQL (InnoDB) setzt du damit unter eine Bewährungsprobe, die Caches sind per Default relativ klein eingestellt, wenn nun jeweils einen so großer Datensatz darin gespeichert wird, müssen andere Daten wieder rausgeräumt werden, es finden viele Cache-Misses statt.
Heißt das jetzt du würdest die tabelle vertikal splitten?
 

Meldanor

Bekanntes Mitglied
Nun ja, du hast ja gesagt, du speichert Informationen über die Mitglieder.
Eventuel doppeln sie sich und du kannst Tabelleninformationen zusammenführen.
Hobbys zum Beispiel in eine andere Tabelle auslagern und statt dem String selber in der Tabelle nur ein int als Verweis auf die andere Tabelle machen. So kürzt du das auch schon.
Wenn du jedoch die Tabelle auf keinen Fall noch weiter aufspalten kannst, dann hat diese Entinität 50 Attribut und diese in 2 Hälften aufspalten, ist wenig sinnvoll, da du dann abwechselnd über beide schreiben müsstest(wenn Tabelle 1 Max ungerade, dann schreibe in Tabelle 2?). Dort müsstest du durch die Spaltung sehr auf Datenkonsistenz achten, weil die kann dann schnell flöten gehen und diesen Aufwand zu relativieren mit dem höheren Leistungsverbraucht ~ würde ich sage, dass lohnt sich nicht, vorallem, weil auch die Übersicht leidet.
 

ice-breaker

Top Contributor
Heißt das jetzt du würdest die tabelle vertikal splitten?
ja, 50 sind sowieso zuviel, da behält doch keiner den Überblick.
Ich würde das aufteilen in Attribute, die oft genutzt werden (damit diese regelmäßig im cache sind), und attribute die seltener genutzt werden, und diese wahrscheinlich noch sinnvoll aufteilen.

Aber ich denke mal die Normalformen werden dir die 50-spaltige Tabelle sowieso aufsplitten.
 
G

Gast2

Gast
Hilft mir bei meinem Problem aber nicht weiter, denn meine Riesentabelle ist ja in BCNF.

nein ist sie nicht ... Deine Datenbank hat noch nicht mal die 1. Normalform erreicht ... oder haben Deine Mitgliieder nur ein Hobby? ... wie trennst Du die Hobbys untereinander in der Spalte? ... öhm - Lieblingsmusik? ... %WASAUCHIMMER

Wikipedia - 1. Normalform hat gesagt.:
Jedes Attribut der Relation muss einen atomaren Wertebereich haben und frei von Wiederholungsgruppen sein
Normalisierung (Datenbank) ? Wikipedia
 
nein ist sie nicht ... Deine Datenbank hat noch nicht mal die 1. Normalform erreicht ... oder haben Deine Mitgliieder nur ein Hobby? ... wie trennst Du die Hobbys untereinander in der Spalte? ... öhm - Lieblingsmusik? ... %WASAUCHIMMER


Normalisierung (Datenbank) ? Wikipedia

Die Mitglieder können bei diesen Feldern einen Fließtext eingeben, da soll nicht nach einzelnen Hobbys getrennt werden. Zwei Einträge von zwei verschiedenen mitgliedern könnten zum Beispiel sein:
(1) "Basketball, Fußball, Flugzeugträger besichtigen"
(2) "Ich lese gerne Bücher von Astrid Lindgren"
 

fastjack

Top Contributor
Mach doch einfach mal ein paar Performancetests. Fülle die Tabelle mit tausenden von Zufallszeilen und teste dann select, insert und update. Wie viele Mitglieder sind überhaupt zu erwarten ? Es gibt schon Unterschiede ob es nur Hundert oder eine Million sind.

Ansonsten würde ich auch zur Normalisierung raten, aber es kommt sicherlich auf den konkreten Anwendungsfall an. Eine Historientabelle, bestehend aus millionen von Datenzeilen würde ich im ganzen Leben nie wieder normalisieren. Bei Stammdatentabellen, die immer wieder gewartet werden, würde ich immer Normalisieren.

Wie willst Du z.B. nach Hobbies gruppieren oder sortieren ?
 

ice-breaker

Top Contributor
Das ist allerdings nicht der Sinn von relationalen Datenbanken

ist aber leider das, was Nutzer von Sozialen Netzwerken (Web-Communitys) erwarten, Facebook und StudiVZ haben es vorgemacht, dann erwarten sie es von allen anderen auch so.

Sollte das Fließtext sein, müssen diese Attribute unbedingt in eine andere Tabelle, denn Text-Spalten wirken sich nicht sehr positiv auf die Performance aus.
Ein Blick auf die Kompression des InnoDB Plugins kann da auch wieder einen gewaltigen Performanceschub bringen ;)
 

ice-breaker

Top Contributor
Datenhaltung und Datendarstellung sind zwei Geschichten ... MVC
richtig, nun sag mir aber wie du fließtext, in der jemand seine Hobbys beschreibt (Auflistung vs. Roman), sinnvoll in einer relationalen Datenbank speichern willst, das geht eben nicht.

Auf Deutsch: In der Darstellung wird Fließtext von den Nutzern gefordert, aus diesem Grunde hast du aber bei der Datenhaltung eine Abhängigkeit von der Dateneingabe.
 
G

Gast2

Gast
Trennung anhand der Komma ... evt. noch Leerzeichen (kann aber nach hinten los gehen)
 

ice-breaker

Top Contributor
Hobbys von Mogel:

Typ1: "Rad fahren, Fitnessstudio"

Typ2: "Früher bin ich viel Rad gefahren, aber seit dem der Wanderweg im Wald gesperrt wurde, fahre ich kaum noch, aber dafür habe ich ja ein Fitness-Studio um die Ecke, welches von mir regelmäßig besucht wird"

Für Typ1 mag das trennen noch gehen, aber da wir eine Textbox anbieten, die keine Regeln für die Eingabe macht, können wir nicht implizieren, dass alles nach Typ1 eingegeben wird, also bleibt uns nur die Möglichkeit es auch als Fließtext zu speichern, da auch Personen Typ2 eingeben können, das meine ich damit.

Teilweise ist die Datenhaltung von der Datendarstellung abhängig und Konzepte der relationalen Datenbanken müssen aufgebrochen werden.
 
G

Gast2

Gast
Du kannst das aber über eine zweite Tabelle und einen FK "verstecken"
 

robertpic71

Bekanntes Mitglied
Als erstes: Selbst "schwache" Datenbanken sollten solche Fehldesigns locker wegstecken. Ich gehe einmal davon aus, dass du die 10.000 Marke nicht wesentlich übersteigst. Bei diversen "Legacy-Anwendungen" müssen die Datenbank viel mehr aushalten...

Die Größe der Resultsets hängt ja nicht nur von der Tabelle ab, sondern auch davon, wieviel Felder man im Select angibt.
Ein Select Id, Name, password from mitglieder liefert nur diese 3 Felder zurück.

Wie schon von Anderen angesprochen, da gibt es Faktoren, welche dich (mit wenig DB Wissen) eher ausbremsen.

- wenn immer Möglich: die Selektion mit dem SQL where abdecken
- für die Zugriff einen Index anbieten, also z.B. Nach Mitgielder Index nach Name für die Passwortprüfung (damit scannt er nicht die ganze Datei durch)

und 1000+1 "kleine Tipps" als PreparedStatement verwenden usw.

Zur Anforderung der Hobbies:
Es wird immer wieder Anforderungen nach "unstrukturierten" Daten geben. Das ist solange kein Problem, bis man die Daten irgendwie filtern, prüfen oder sonst irgendwie auswerten will.

Bei kleinen Datenmengen wird es keine Rolle spielen, aber ich vermeide Fließtextfelder in der Hauptdatei.


/Robert
 

mabus

Mitglied
Hallo,

folgendes szenario:
Ich schreibe ein Web-Communityskript und benutzte eine MySql-Datenbank.
In der DB gibt es eine Tabelle "Mitglieder". Dort sind für alle mitglieder neben benutzername und passwort noch eine Menge anderer Daten gespeichert, von Namen und Adresse über Hobbys bis Lieblingsmusik. Insgesamt ca. 50 felder.
Wäre es sinnvoll diese Tabelle in mehrere Tabellen aufzuspalten?

Wenn ich jetzt auf einer Seite einen Aufruf "Select Benutzer_ID From Mitglieder where...." mache, läd dann mein DBS erstmal die ganze riesen Mitgliedertabelle und pickt dann raus was gebraucht wird? In dem Fall wäre es ja aufjedenfall besser die tabelle zu splitten.

Hatte zwar mal ne DBS vorlesung, weiß da aber leider nicht mehr so genau bescheid und bevor ich was unglaublich ressourcenfressendes programmiere frag ich lieber mal nach ;-)


Danke für eure Hilfe
P.C.

PS: Ich meine mit Splitten nicht, dass ich die ersten x rows in eine tabelle packe und die nächsten in ne andere, sondern splitten indem ich z.B. in einer Tabelle nur username und passwort speichere, in eine andere namen und adressen, in eine andere hobbies und interessen, etc. obwohl das von den Normalformen her eigentlich nicht nötig wäre.

Hm..ich würde mir in deinem Falle erstmal Gedanken um die Use-Cases machen. Der Name einer Person (eines Mitgliedes) wird vermutlich wesentlich häufiger abgerufen werden (z.b. Suche, Freundesliste, etc) als seine Interessen, Hobbies und dergleichen (Profilseite)...

Ergo macht es durchaus schon Sinn, die Daten ein wenig danach zu trennen, zu welchen Zwecken sie benötigt werden (also als Beispiel Stammdaten und personenbezogene Detaildaten).
 
Status
Nicht offen für weitere Antworten.
Ähnliche Java Themen
  Titel Forum Antworten Datum
B Performance steigern, aber wie? Datenbankprogrammierung 8
V SQLite Performance: 1 Datei mit einzelnen Einträgen gegenüber SQLite Datenbankprogrammierung 7
S HSQLDB Performance von CHECKPOINT Datenbankprogrammierung 1
R Oracle Performance bei SELECT mit vielen Reihen Datenbankprogrammierung 5
X Connection schließen oder speichern? Performance Frage Datenbankprogrammierung 7
A Performance GPS Entfernung berechnen Datenbankprogrammierung 8
F Performance-Tool für Oracle Datenbankprogrammierung 2
D mysql insert - performance/robustheit, "best practice" Datenbankprogrammierung 15
H performance frage Datenbankprogrammierung 9
S Performance bei Massinserts Datenbankprogrammierung 5
V Performance gut? Datenbankprogrammierung 22
O Derby Performance Probleme? Datenbankprogrammierung 4
G JDBC - Performance Datenbankprogrammierung 4
A HSQLDB Performance bei erstem Zugriff Datenbankprogrammierung 6
Y Hibernate - Performance Datenbankprogrammierung 6
M JDBC-Performance extrem schlecht - Konfigurationsfehler? Datenbankprogrammierung 4
A Viele Abfragen auf einmal: Performance Datenbankprogrammierung 2
J MySQL - executeUpdate - Performance Datenbankprogrammierung 13
R hsqldb: performance, große tabellen und so Datenbankprogrammierung 10
R db4o und Performance Datenbankprogrammierung 5
S ResultSet, Performance Datenbankprogrammierung 18
G Datenbank: Performance Tuning Datenbankprogrammierung 4
P Datenbank Tool - besser als oracle SQL Developer gesucht mit effizinte Verbindungsverwaltung Datenbankprogrammierung 2
feinperligekohlensaeure MySQL Dynamische Tabellen. Wie kann man es besser machen? Datenbankprogrammierung 3
E Welches Datenbankmanagementsystem ist besser geeignet? Datenbankprogrammierung 1
I Was ist besser: Tabellen oder Spalten Datenbankprogrammierung 1

Ähnliche Java Themen

Neue Themen


Oben