it-swarm.com.de

Datenbankentwicklungsfehler von Anwendungsentwicklern

Was sind häufige Fehler bei der Datenbankentwicklung, die von Anwendungsentwicklern gemacht werden?

566
Charles Faiga

1. Keine passenden Indizes verwenden

Dies ist relativ einfach, aber es passiert die ganze Zeit. Fremdschlüssel sollten mit Indizes versehen sein. Wenn Sie ein Feld in einem WHERE verwenden, sollten Sie (wahrscheinlich) einen Index haben. Solche Indizes sollten häufig mehrere Spalten umfassen, basierend auf den Abfragen, die Sie ausführen müssen.

2. Referentielle Integrität nicht erzwingen

Ihre Datenbank kann hier variieren. Wenn Ihre Datenbank jedoch referenzielle Integrität unterstützt, dh, alle Fremdschlüssel verweisen garantiert auf eine vorhandene Entität, sollten Sie sie verwenden.

Es ist durchaus üblich, dass dieser Fehler in MySQL-Datenbanken auftritt. Ich glaube nicht, dass MyISAM dies unterstützt. InnoDB macht. Sie werden Leute finden, die MyISAM benutzen oder die InnoDB benutzen, es aber trotzdem nicht benutzen.

Mehr hier:

3. Verwenden natürlicher Primärschlüssel anstelle von (technischen) Ersatzschlüsseln

Natural Keys sind Schlüssel, die auf extern aussagekräftigen Daten basieren, die (scheinbar) eindeutig sind. Gängige Beispiele sind Produktcodes, aus zwei Buchstaben bestehende Statuscodes (US), Sozialversicherungsnummern usw. Ersatz- oder technische Primärschlüssel sind solche, die außerhalb des Systems überhaupt keine Bedeutung haben. Sie dienen lediglich der Identifizierung der Entität und sind in der Regel automatisch inkrementierende Felder (SQL Server, MySQL usw.) oder Sequenzen (insbesondere Oracle).

Meiner Meinung nach sollten Sie immer Ersatzschlüssel verwenden. Dieses Problem ist in folgenden Fragen aufgetreten:

Dies ist ein etwas kontroverses Thema, über das Sie sich nicht allgemein einigen können. Während Sie vielleicht einige Leute finden, die denken, dass natürliche Schlüssel in einigen Situationen in Ordnung sind, werden Sie keine Kritik an Ersatzschlüsseln finden, außer, dass sie möglicherweise unnötig sind. Das ist ein kleiner Nachteil, wenn Sie mich fragen.

Denken Sie daran, auch Länder können aufhören zu existieren (zum Beispiel Jugoslawien).

4. Abfragen schreiben, für die DISTINCT erforderlich ist

Sie sehen dies häufig in ORM-generierten Abfragen. Sehen Sie sich die Protokollausgabe von Hibernate an und sehen Sie, dass alle Abfragen mit Folgendem beginnen:

SELECT DISTINCT ...

Dies ist eine Abkürzung, um sicherzustellen, dass Sie keine doppelten Zeilen zurückgeben und somit doppelte Objekte erhalten. Manchmal sieht man auch Leute, die das tun. Wenn Sie es zu viel sehen, ist es eine echte rote Fahne. Nicht, dass DISTINCT schlecht ist oder keine gültigen Anwendungen hat. Dies ist zwar in beiden Punkten der Fall, jedoch kein Ersatz oder eine Lücke für das Schreiben korrekter Abfragen.

Von Warum ich HASSE, UNTERSCHEIDEN :

Meiner Meinung nach beginnen die Dinge schlecht zu laufen, wenn ein Entwickler umfangreiche Abfragen erstellt, Tabellen zusammenfügt und plötzlich merkt, dass es so aussieht als würde er doppelte (oder noch mehr) Zeilen erhalten und sofort antworten ... seine "Lösung" für dieses "Problem" besteht darin, das DISTINCT-Schlüsselwort und [~ # ~] poof zu verwenden [~ # ~] alle seine Probleme verschwinden.

5. Bevorzugen der Aggregation gegenüber Joins

Ein weiterer häufiger Fehler von Datenbankanwendungsentwicklern besteht darin, nicht zu erkennen, wie viel teurer die Aggregation (dh die GROUP BY - Klausel) im Vergleich zu Joins ist.

Um Ihnen eine Vorstellung davon zu geben, wie weit verbreitet dies ist, habe ich hier einige Male zu diesem Thema geschrieben und es wurde viel dafür abgelehnt. Zum Beispiel:

Von SQL-Anweisung - "Join" vs "Group by and Having" :

Erste Abfrage:

SELECT userid
FROM userrole
WHERE roleid IN (1, 2, 3)
GROUP by userid
HAVING COUNT(1) = 3

Abfragezeit: 0,312 s

Zweite Abfrage:

SELECT t1.userid
FROM userrole t1
JOIN userrole t2 ON t1.userid = t2.userid AND t2.roleid = 2
JOIN userrole t3 ON t2.userid = t3.userid AND t3.roleid = 3
AND t1.roleid = 1

Abfragezeit: 0.016 s

Stimmt. Die von mir vorgeschlagene Join-Version ist zwanzigmal schneller als die aggregierte Version.

6. Komplexe Abfragen nicht durch Views vereinfachen

Nicht alle Datenbankanbieter unterstützen Ansichten, aber für diejenigen, die dies tun, können sie Abfragen erheblich vereinfachen, wenn sie mit Bedacht verwendet werden. Beispielsweise habe ich für ein Projekt ein generisches Partymodell für CRM verwendet. Dies ist eine äußerst leistungsstarke und flexible Modellierungstechnik, die jedoch zu vielen Verknüpfungen führen kann. In diesem Modell gab es:

  • Partei : Menschen und Organisationen;
  • Parteirolle : Dinge, die diese Parteien getan haben, zum Beispiel Mitarbeiter und Arbeitgeber;
  • Parteirollenbeziehung : In welcher Beziehung stehen diese Rollen zueinander?.

Beispiel:

  • Ted ist eine Person, die ein Subtyp der Partei ist.
  • Ted hat viele Rollen, eine davon ist Angestellter;
  • Intel ist eine Organisation, die ein Subtyp einer Partei ist.
  • Intel hat viele Rollen, von denen eine Arbeitgeber ist;
  • Intel beschäftigt Ted, was bedeutet, dass eine Beziehung zwischen den jeweiligen Rollen besteht.

Es sind also fünf Tische verbunden, um Ted mit seinem Arbeitgeber zu verbinden. Sie gehen davon aus, dass alle Mitarbeiter Personen (nicht Organisationen) sind, und geben diese Hilfsansicht an:

CREATE VIEW vw_employee AS
SELECT p.title, p.given_names, p.surname, p.date_of_birth, p2.party_name employer_name
FROM person p
JOIN party py ON py.id = p.id
JOIN party_role child ON p.id = child.party_id
JOIN party_role_relationship prr ON child.id = prr.child_id AND prr.type = 'EMPLOYMENT'
JOIN party_role parent ON parent.id = prr.parent_id = parent.id
JOIN party p2 ON parent.party_id = p2.id

Und plötzlich haben Sie eine sehr einfache Sicht auf die gewünschten Daten, jedoch auf ein hochflexibles Datenmodell.

7. Eingabe wird nicht bereinigt

Dies ist ein riesiger. Jetzt mag ich PHP, aber wenn Sie nicht wissen, was Sie tun, ist es wirklich einfach, Websites zu erstellen, die anfällig für Angriffe sind. Nichts fasst es besser zusammen als die Geschichte von kleinen Bobby Tables .

Vom Benutzer über URLs, Formulardaten und Cookies bereitgestellte Daten sollten immer als feindselig und bereinigt behandelt werden. Stellen Sie sicher, dass Sie das bekommen, was Sie erwarten.

8. Keine vorbereiteten Anweisungen verwenden

Vorbereitete Anweisungen werden erstellt, wenn Sie eine Abfrage ohne die in Einfügungen, Aktualisierungen und WHERE -Klauseln verwendeten Daten kompilieren und diese später bereitstellen. Zum Beispiel:

SELECT * FROM users WHERE username = 'bob'

vs

SELECT * FROM users WHERE username = ?

oder

SELECT * FROM users WHERE username = :username

abhängig von Ihrer Plattform.

Ich habe gesehen, wie Datenbanken auf diese Weise in die Knie gezwungen wurden. Grundsätzlich muss jede moderne Datenbank, die auf eine neue Abfrage stößt, diese kompilieren. Wenn es auf eine Abfrage stößt, die es zuvor gesehen hat, geben Sie der Datenbank die Möglichkeit, die kompilierte Abfrage und den Ausführungsplan zwischenzuspeichern. Wenn Sie die Abfrage häufig ausführen, erhalten Sie die Möglichkeit, dies herauszufinden und entsprechend zu optimieren (z. B. durch Fixieren der kompilierten Abfrage im Speicher).

Mit vorbereiteten Anweisungen erhalten Sie aussagekräftige Statistiken darüber, wie oft bestimmte Abfragen verwendet werden.

Vorbereitete Anweisungen schützen Sie auch besser vor SQL-Injection-Angriffen.

9. Nicht normalisierend genug

Datenbanknormalisierung ist im Grunde der Prozess der Optimierung des Datenbankdesigns oder der Organisation Ihrer Daten in Tabellen.

Gerade diese Woche bin ich auf einen Code gestoßen, bei dem jemand ein Array implodiert und in ein einzelnes Feld in einer Datenbank eingefügt hat. Normalisieren Sie dies, indem Sie das Element dieses Arrays als separate Zeile in einer untergeordneten Tabelle behandeln (dh als eine Eins-zu-Viele-Beziehung).

Dies kam auch in Beste Methode zum Speichern einer Liste von Benutzer-IDs :

Ich habe in anderen Systemen gesehen, dass die Liste in einem serialisierten PHP Array gespeichert ist.

Der Mangel an Normalisierung tritt jedoch in vielerlei Hinsicht auf.

Mehr:

10. Zu viel normalisieren

Dies mag wie ein Widerspruch zum vorherigen Punkt erscheinen, aber die Normalisierung ist wie viele andere Dinge ein Werkzeug. Es ist ein Mittel zum Zweck und kein Selbstzweck. Ich denke, viele Entwickler vergessen dies und fangen an, ein "Mittel" als "Zweck" zu behandeln. Unit Testing ist ein Paradebeispiel dafür.

Ich habe einmal an einem System mit einer riesigen Hierarchie für Kunden gearbeitet, die ungefähr so ​​aussah:

Licensee ->  Dealer Group -> Company -> Practice -> ...

sie mussten ungefähr 11 Tabellen zusammenfügen, bevor Sie aussagekräftige Daten erhalten konnten. Es war ein gutes Beispiel für eine zu weit gehende Normalisierung.

Um es auf den Punkt zu bringen: Eine sorgfältige und überlegte Denormalisierung kann enorme Leistungsvorteile mit sich bringen. Dabei muss man jedoch sehr vorsichtig sein.

Mehr:

11. Verwenden von exklusiven Bögen

Ein exklusiver Bogen ist ein häufiger Fehler, bei dem eine Tabelle mit zwei oder mehr Fremdschlüsseln erstellt wird, von denen einer und nur einer nicht null sein kann. Großer Fehler. Zum einen wird es immer schwieriger, die Datenintegrität aufrechtzuerhalten. Schließlich hindert auch bei referentieller Integrität nichts daran, zwei oder mehr dieser Fremdschlüssel zu setzen (trotz komplexer Prüfungseinschränkungen).

Von Ein praktischer Leitfaden zum relationalen Datenbankdesign :

Wir haben nachdrücklich davon abgeraten, wo immer möglich einen exklusiven Lichtbogen zu konstruieren, aus dem guten Grund, dass es schwierig sein kann, Code zu schreiben und mehr Wartungsschwierigkeiten zu verursachen.

12. Keine Leistungsanalyse für Abfragen

Vor allem in der Datenbankwelt hat Pragmatismus oberste Priorität. Wenn Sie sich an Grundsätze halten, bis sie zu einem Dogma geworden sind, haben Sie höchstwahrscheinlich Fehler gemacht. Nehmen Sie das Beispiel der aggregierten Abfragen von oben. Die Gesamtversion sieht vielleicht "gut" aus, aber die Leistung ist bedauerlich. Ein Leistungsvergleich hätte die Debatte beenden sollen (hat es aber nicht getan), aber mehr auf den Punkt gebracht: Solche schlecht informierten Ansichten auszusprechen ist ignorant, ja sogar gefährlich.

13. Übermäßige Abhängigkeit von UNION ALL und insbesondere von UNION-Konstrukten

Eine UNION in SQL-Begriffen verkettet lediglich kongruente Datensätze, dh sie haben den gleichen Typ und die gleiche Anzahl von Spalten. Der Unterschied besteht darin, dass UNION ALL eine einfache Verkettung ist und nach Möglichkeit bevorzugt wird, während UNION implizit DISTINCT ausführt, um doppelte Tupel zu entfernen.

Gewerkschaften haben wie DISTINCT ihren Platz. Es gibt gültige Bewerbungen. Wenn Sie jedoch feststellen, dass Sie eine Menge davon tun, insbesondere in Unterabfragen, dann tun Sie wahrscheinlich etwas Falsches. Dies kann auf eine schlechte Abfragekonstruktion oder ein schlecht entworfenes Datenmodell zurückzuführen sein, das Sie dazu zwingt, solche Dinge zu tun.

UNIONs können, insbesondere wenn sie in Joins oder abhängigen Unterabfragen verwendet werden, eine Datenbank lahm legen. Versuchen Sie, sie nach Möglichkeit zu meiden.

14. OR Bedingungen in Abfragen verwenden

Das mag harmlos erscheinen. ANDs sind schließlich in Ordnung. OR sollte auch OK sein, oder? Falsch. Grundsätzlich schränkt eine UND-Bedingung den Datensatz ein , während eine OR - Bedingung wächst es aber nicht in einer Weise, die sich zur Optimierung anbietet. Insbesondere wenn sich die verschiedenen OR - Bedingungen überschneiden könnten, wird der Optimierer gezwungen, eine DISTINCT-Operation für das Ergebnis durchzuführen.

Schlecht:

... WHERE a = 2 OR a = 5 OR a = 11

Besser:

... WHERE a IN (2, 5, 11)

Jetzt kann Ihr SQL-Optimierer die erste Abfrage effektiv in die zweite umwandeln. Möglicherweise aber nicht. Tu es einfach nicht.

15. Ihr Datenmodell nicht so zu gestalten, dass es sich für leistungsstarke Lösungen eignet

Dies ist schwer zu quantifizieren. Es wird typischerweise durch seine Wirkung beobachtet. Wenn Sie feststellen, dass Sie knifflige Abfragen für relativ einfache Aufgaben schreiben oder dass Abfragen zum Herausfinden relativ einfacher Informationen nicht effizient sind, haben Sie wahrscheinlich ein schlechtes Datenmodell.

In gewisser Weise fasst dieser Punkt alle früheren zusammen, aber es ist eher eine Warnung, dass Dinge wie die Abfrageoptimierung oft als erstes ausgeführt werden, wenn dies als zweites ausgeführt werden sollte. In erster Linie sollten Sie sicherstellen, dass Sie ein gutes Datenmodell haben, bevor Sie versuchen, die Leistung zu optimieren. Wie Knuth sagte:

Vorzeitige Optimierung ist die Wurzel allen Übels

16. Falsche Verwendung von Datenbanktransaktionen

Alle Datenänderungen für einen bestimmten Prozess sollten atomar sein. Das heißt Wenn die Operation erfolgreich ist, wird sie vollständig ausgeführt. Wenn dies fehlschlägt, bleiben die Daten unverändert. - Es sollte keine Möglichkeit für "halbfertige" Änderungen geben.

Der einfachste Weg, dies zu erreichen, besteht im Idealfall darin, dass das gesamte Systemdesign danach strebt, alle Datenänderungen durch einzelne INSERT/UPDATE/DELETE-Anweisungen zu unterstützen. In diesem Fall ist keine spezielle Transaktionsbehandlung erforderlich, da dies von Ihrem Datenbankmodul automatisch durchgeführt werden sollte.

Wenn für Prozesse jedoch mehrere Anweisungen als Einheit ausgeführt werden müssen, um den konsistenten Zustand der Daten zu gewährleisten, ist eine entsprechende Transaktionssteuerung erforderlich.

  • Beginnen Sie eine Transaktion vor der ersten Anweisung.
  • Übernehmen Sie die Transaktion nach der letzten Anweisung.
  • Führen Sie bei einem Fehler ein Rollback der Transaktion durch. Und sehr NB! Vergessen Sie nicht, alle nach dem Fehler folgenden Anweisungen zu überspringen/abzubrechen.

Es wird außerdem empfohlen, die Feinheiten der Interaktion zwischen Datenbankkonnektivitätsebene und Datenbankmodul in dieser Hinsicht sorgfältig zu berücksichtigen.

17. Das "satzbasierte" Paradigma nicht verstehen

Die SQL-Sprache folgt einem bestimmten Paradigma, das für bestimmte Arten von Problemen geeignet ist. Ungeachtet verschiedener herstellerspezifischer Erweiterungen hat die Sprache Schwierigkeiten, mit Problemen umzugehen, die in Sprachen wie Java, C #, Delphi usw. trivial sind.

Dieser Mangel an Verständnis äußert sich auf verschiedene Arten.

  • Der Datenbank zu viel prozedurale oder imperative Logik auferlegen.
  • Unangemessene oder übermäßige Verwendung von Cursorn. Vor allem, wenn eine einzige Abfrage ausreichen würde.
  • Es wird fälschlicherweise davon ausgegangen, dass bei mehrzeiligen Aktualisierungen einmal pro Zeile ein Auslöser ausgelöst wird.

Stellen Sie eine klare Aufteilung der Verantwortung fest und bemühen Sie sich, jedes Problem mit dem geeigneten Werkzeug zu lösen.

1003
cletus

Schlüsseldatenbankdesign und Programmierfehler von Entwicklern

  • Eigennützige Datenbankgestaltung und -nutzung. Entwickler behandeln die Datenbank häufig als ihren persönlichen dauerhaften Objektspeicher, ohne die Bedürfnisse anderer Beteiligter in den Daten zu berücksichtigen. Dies gilt auch für Anwendungsarchitekten. Schlechtes Datenbankdesign und Datenintegrität erschweren die Arbeit mit den Daten für Dritte und können die Lebenszykluskosten des Systems erheblich erhöhen. Reporting und MIS sind in der Regel ein schlechter Verwandter im Anwendungsdesign und werden nur nachträglich durchgeführt.

  • Missbrauch denormalisierter Daten Das Übertreiben denormalisierter Daten und der Versuch, sie in der Anwendung zu verwalten, sind ein Rezept für Datenintegritätsprobleme. Denormalisierung sparsam einsetzen. Das Nicht-Hinzufügen eines Joins zu einer Abfrage ist keine Entschuldigung für eine Denormalisierung.

  • Ich habe Angst davor, SQL zu schreiben. SQL ist kein Hexenwerk und kann seine Arbeit eigentlich recht gut erledigen. O/R-Zuordnungsebenen können die 95% der Abfragen, die einfach sind und gut in dieses Modell passen, recht gut ausführen. Manchmal ist SQL der beste Weg, um die Arbeit zu erledigen.

  • Dogmatische Richtlinien für "Keine gespeicherten Prozeduren" Unabhängig davon, ob Sie gespeicherte Prozeduren für böse halten, hat diese dogmatische Einstellung keinen Platz in einem Softwareprojekt.

  • Datenbankdesign nicht verstehen. Normalisierung ist dein Freund und es ist keine Hexerei. Verbinden und Kardinalität sind ziemlich einfache Konzepte - wenn du Ich bin an der Entwicklung von Datenbankanwendungen beteiligt. Es gibt wirklich keine Entschuldigung, sie nicht zu verstehen.

  1. Keine Versionskontrolle für das Datenbankschema
  2. Direkt gegen eine Live-Datenbank arbeiten
  3. Weiterführende Datenbankkonzepte (Indizes, Clustered-Indizes, Einschränkungen, materialisierte Ansichten usw.) nicht lesen und verstehen
  4. Wenn Sie die Skalierbarkeit nicht testen ... Mit Testdaten von nur 3 oder 4 Zeilen erhalten Sie nie das richtige Bild der tatsächlichen Live-Leistung
80
Rad

Überbeanspruchung und/oder Abhängigkeit von gespeicherten Prozeduren.

Einige Anwendungsentwickler betrachten gespeicherte Prozeduren als direkte Erweiterung des Middle Tier/Front End-Codes. Dies scheint eine häufige Eigenschaft bei Microsoft-Stack-Entwicklern zu sein (ich bin eine, aber ich bin daraus herausgewachsen) und produziert viele gespeicherte Prozeduren, die komplexe Geschäftslogik und Workflow-Verarbeitung ausführen. Dies ist anderswo viel besser gemacht.

Gespeicherte Prozeduren sind nützlich, wenn tatsächlich nachgewiesen wurde, dass ein realer technischer Faktor deren Verwendung erforderlich macht (z. B. Leistung und Sicherheit). Zum Beispiel, um die Aggregation/Filterung großer Datensätze "nah an den Daten" zu halten.

Ich musste kürzlich bei der Wartung und Verbesserung einer großen Delphi-Desktop-Anwendung helfen, von der 70% der Geschäftslogik und -regeln in 1400 gespeicherten SQL Server-Prozeduren implementiert wurden (der Rest in UI-Ereignishandlern). Dies war ein Albtraum, vor allem aufgrund der schwierigen Einführung effektiver Unit-Tests in TSQL, mangelnder Kapselung und schlechter Tools (Debugger, Editoren).

Als ich in der Vergangenheit mit einem Java - Team gearbeitet habe, stellte ich schnell fest, dass in dieser Umgebung oft das genaue Gegenteil der Fall ist. Ein Java - Architekt sagte mir einmal: "Die Datenbank ist für Daten, nicht Code. ".

Heutzutage halte ich es für einen Fehler, gespeicherte Prozesse überhaupt nicht zu berücksichtigen, aber sie sollten sparsam (nicht standardmäßig) in Situationen verwendet werden, in denen sie nützliche Vorteile bieten (siehe die anderen Antworten).

46
Ash

Problem Nummer eins? Sie testen nur auf Spielzeugdatenbanken. Sie haben also keine Ahnung, dass ihr SQL-Code crawlt, wenn die Datenbank groß wird, und jemand muss mitkommen und es später reparieren (das Geräusch, das Sie hören können, ist mein Zähneknirschen).

41
Bob Moore

Keine Indizes verwenden.

31

Schlechte Leistung durch korrelierte Unterabfragen

Meistens möchten Sie korrelierte Unterabfragen vermeiden. Eine Unterabfrage ist korreliert, wenn in der Unterabfrage ein Verweis auf eine Spalte aus der äußeren Abfrage vorhanden ist. In diesem Fall wird die Unterabfrage mindestens einmal für jede zurückgegebene Zeile ausgeführt und kann mehrmals ausgeführt werden, wenn andere Bedingungen angewendet werden, nachdem die Bedingung angewendet wurde, die die korrelierte Unterabfrage enthält.

Verzeihen Sie das erfundene Beispiel und die Oracle-Syntax, aber nehmen wir an, Sie wollten alle Mitarbeiter finden, die in einem Ihrer Geschäfte seit dem letzten Mal eingestellt wurden, als das Geschäft weniger als 10.000 US-Dollar an einem Tag verkaufte.

select e.first_name, e.last_name
from employee e
where e.start_date > 
        (select max(ds.transaction_date)
         from daily_sales ds
         where ds.store_id = e.store_id and
               ds.total < 10000)

Die Unterabfrage in diesem Beispiel wird durch die store_id mit der äußeren Abfrage korreliert und für jeden Mitarbeiter in Ihrem System ausgeführt. Eine Möglichkeit, diese Abfrage zu optimieren, besteht darin, die Unterabfrage in eine Inline-Ansicht zu verschieben.

select e.first_name, e.last_name
from employee e,
     (select ds.store_id,
             max(s.transaction_date) transaction_date
      from daily_sales ds
      where ds.total < 10000
      group by s.store_id) dsx
where e.store_id = dsx.store_id and
      e.start_date > dsx.transaction_date

In diesem Beispiel ist die Abfrage in der from-Klausel jetzt eine Inline-Ansicht (wieder einige Oracle-spezifische Syntax) und wird nur einmal ausgeführt. Abhängig von Ihrem Datenmodell wird diese Abfrage wahrscheinlich viel schneller ausgeführt. Es würde eine bessere Leistung als die erste Abfrage erbringen, wenn die Anzahl der Mitarbeiter ansteigt. Die erste Abfrage könnte tatsächlich eine bessere Leistung erbringen, wenn nur wenige Mitarbeiter und viele Geschäfte vorhanden sind (und möglicherweise viele Geschäfte keine Mitarbeiter haben) und die daily_sales-Tabelle für store_id indiziert wurde. Dies ist kein wahrscheinliches Szenario, zeigt jedoch, wie eine korrelierte Abfrage möglicherweise eine bessere Leistung als eine Alternative erzielen kann.

Ich habe gesehen, dass Nachwuchsentwickler häufig Unterabfragen korrelierten, und dies hatte normalerweise schwerwiegende Auswirkungen auf die Leistung. Beachten Sie jedoch beim Entfernen einer korrelierten Unterabfrage unbedingt Plan erklären vor und nach, um sicherzustellen, dass Sie die Leistung nicht verschlechtern.

28
adam

Durch meine Erfahrung:
Keine Kommunikation mit erfahrenen Datenbankadministratoren.

21
Kb.

Verwenden von Access anstelle einer "echten" Datenbank. Es gibt viele großartige kleine und sogar kostenlose Datenbanken wie SQL Express , MySQL und SQLite , die viel besser funktionieren und skaliert werden können. Apps müssen häufig auf unerwartete Weise skaliert werden.

17
Nathan Voxland

Vergessen, Beziehungen zwischen den Tabellen einzurichten. Ich erinnere mich, dass ich das aufräumen musste, als ich anfing, bei meinem jetzigen Arbeitgeber zu arbeiten.

16
TheTXI

Ich möchte hinzufügen: Bevorzugen von "elegantem" Code gegenüber leistungsstarkem Code. Der Code, der am besten für Datenbanken geeignet ist, ist für den Anwendungsentwickler häufig hässlich.

Den Unsinn über vorzeitige Optimierung glauben. Datenbanken müssen die Leistung im ursprünglichen Entwurf und in jeder nachfolgenden Entwicklung berücksichtigen. Die Performance beträgt meiner Meinung nach 50% des Datenbankdesigns (40% sind Datenintegrität und die letzten 10% Sicherheit). Datenbanken, deren Leistung nicht von Grund auf neu erstellt wurde, weisen eine schlechte Leistung auf, wenn echte Benutzer und echter Datenverkehr für die Datenbank verwendet werden. Vorzeitige Optimierung bedeutet nicht, keine Optimierung! Das bedeutet nicht, dass Sie Code schreiben sollten, der fast immer eine schlechte Leistung erbringt, weil Sie es einfacher finden (Cursor zum Beispiel, die in einer Produktionsdatenbank niemals zugelassen werden sollten, wenn nicht alles andere fehlgeschlagen ist). Es bedeutet, dass Sie sich nicht darum kümmern müssen, das letzte bisschen Leistung herauszuholen, bis Sie es müssen. Es ist viel darüber bekannt, was bei Datenbanken besser abschneidet. Dies bei Design und Entwicklung zu ignorieren, ist bestenfalls kurzsichtig.

14
HLGEM

Verwendung von Excel zum Speichern (großer Datenmengen).

Ich habe Firmen gesehen, die Tausende von Zeilen besaßen und mehrere Arbeitsblätter verwendeten (aufgrund des Zeilenlimits von 65535 in früheren Versionen von Excel).


Excel eignet sich gut für Berichte, Datenpräsentationen und andere Aufgaben, sollte jedoch nicht als Datenbank behandelt werden.

14
ML--

Keine parametrisierten Abfragen verwenden. Sie sind ziemlich praktisch beim Stoppen von SQL Injection .

Dies ist ein spezielles Beispiel dafür, dass Eingabedaten nicht bereinigt werden, wie in einer anderen Antwort erwähnt.

13
Ash

Ich hasse es, wenn Entwickler verschachtelte SELECT-Anweisungen verwenden oder sogar das Ergebnis einer SELECT-Anweisung im SELECT-Teil einer Abfrage zurückgeben.

Eigentlich wundert es mich, dass ich das hier nirgendwo anders sehe, vielleicht habe ich es übersehen, obwohl @adam auf ein ähnliches Problem hingewiesen hat.

Beispiel:

SELECT
    (SELECT TOP 1 SomeValue FROM SomeTable WHERE SomeDate = c.Date ORDER BY SomeValue desc) As FirstVal
    ,(SELECT OtherValue FROM SomeOtherTable WHERE SomeOtherCriteria = c.Criteria) As SecondVal
FROM
    MyTable c

In diesem Szenario ist das Ergebnis, wenn MyTable 10000 Zeilen zurückgibt, so, als ob die Abfrage gerade 20001 Abfragen ausgeführt hätte, da die ursprüngliche Abfrage plus Abfrage jeder anderen Tabelle einmal für jede Ergebniszeile ausgeführt werden musste.

Entwickler können mit dieser Arbeit in einer Entwicklungsumgebung durchkommen, in der sie nur wenige Datenzeilen zurückgeben und die Untertabellen normalerweise nur eine geringe Datenmenge aufweisen. In einer Produktionsumgebung kann diese Art von Abfrage jedoch mit entsprechend höheren Kosten verbunden sein Daten werden zu den Tabellen hinzugefügt.

Ein besseres (nicht unbedingt perfektes) Beispiel wäre etwa:

SELECT
     s.SomeValue As FirstVal
    ,o.OtherValue As SecondVal
FROM
    MyTable c
    LEFT JOIN (
        SELECT SomeDate, MAX(SomeValue) as SomeValue
        FROM SomeTable 
        GROUP BY SomeDate
     ) s ON c.Date = s.SomeDate
    LEFT JOIN SomeOtherTable o ON c.Criteria = o.SomeOtherCriteria

Auf diese Weise können die Datenbankoptimierer die Daten zusammenmischen, anstatt sie für jeden Datensatz aus der Haupttabelle neu anzufordern. Wenn ich den Code korrigieren muss, bei dem dieses Problem aufgetreten ist, kann ich die Abfragegeschwindigkeit in der Regel um 100% oder mehr erhöhen mehr bei gleichzeitiger Reduzierung der CPU- und Speicherauslastung.

12
CStroliaDavis

Für SQL-basierte Datenbanken:

  1. Keine Nutzung von CLUSTERED INDEXES oder Auswahl der falschen Spalte (n) für CLUSTER.
  2. Verwenden Sie keinen SERIAL (Autonumber) -Datentyp als PRIMARY KEY, um eine Verbindung zu einem FOREIGN KEY (INT) in einer Parent/Child-Tabellenbeziehung herzustellen.
  3. Keine Aktualisierung von Statistiken in einer Tabelle, wenn viele Datensätze eingefügt oder gelöscht wurden.
  4. Nicht reorganisieren (d. H. Entladen, löschen, neu erstellen, laden und neu indizieren) von Tabellen, wenn viele Zeilen eingefügt oder gelöscht wurden (einige Engines behalten gelöschte Zeilen in einer Tabelle mit einem Löschflag bei.)
  5. FRAGMENT ON EXPRESSION (falls unterstützt) für große Tabellen mit hohen Transaktionsraten nicht nutzen.
  6. Auswahl des falschen Datentyps für eine Spalte!
  7. Es wurde kein richtiger Spaltenname ausgewählt.
  8. Keine neuen Spalten am Ende der Tabelle hinzufügen.
  9. Es werden keine richtigen Indizes erstellt, um häufig verwendete Abfragen zu unterstützen.
  10. erstellen von Indizes für Spalten mit wenigen möglichen Werten und Erstellen unnötiger Indizes.
    ... mehr hinzugefügt werden.
12
Frank R.
  • Keine Sicherung vor dem Beheben eines Problems in der Produktionsdatenbank.

  • Verwenden von DDL-Befehlen für gespeicherte Objekte (wie Tabellen, Ansichten) in gespeicherten Prozeduren.

  • Angst vor der Verwendung von gespeicherten Prozessen oder Angst vor der Verwendung von ORM-Abfragen, wo immer diese effizienter/angemessener sind.

  • Ignorieren Sie die Verwendung eines Datenbank-Profilers, der Ihnen genau sagt, in was Ihre ORM-Abfrage letztendlich konvertiert wird, und überprüfen Sie daher die Logik oder sogar das Debuggen, wenn Sie ORM nicht verwenden.

9
WhoIsNinja

1 - Unnötige Verwendung einer Funktion für einen Wert in einer where-Klausel, wobei das Ergebnis dieses Index nicht verwendet wird.

Beispiel:

where to_char(someDate,'YYYYMMDD') between :fromDate and :toDate

anstatt von

where someDate >= to_date(:fromDate,'YYYYMMDD') and someDate < to_date(:toDate,'YYYYMMDD')+1

Und in geringerem Maße: Den Werten, die sie benötigen, keine Funktionsindizes hinzufügen ...

2 - Es werden keine Prüfbedingungen hinzugefügt, um die Gültigkeit der Daten sicherzustellen. Einschränkungen können vom Abfrageoptimierer verwendet werden und tragen WIRKLICH dazu bei, dass Sie Ihren Invarianten vertrauen können. Es gibt einfach keinen Grund, sie nicht zu benutzen.

- Hinzufügen von nicht normalisierten Spalten zu Tabellen aus Faulheit oder Zeitdruck. Die Dinge sind normalerweise nicht so konzipiert, sondern entwickeln sich so weiter. Das Endergebnis ist zweifellos eine Menge Arbeit, die versucht, das Chaos zu beseitigen, wenn Sie bei zukünftigen Entwicklungen von der verlorenen Datenintegrität gebissen werden.

Denken Sie daran, eine Tabelle ohne Daten ist in der Neugestaltung sehr billig. Ein Tisch mit ein paar Millionen Datensätzen ohne Integrität ... nicht so billig umzugestalten. Das richtige Design beim Erstellen der Spalte oder Tabelle wird daher in Pik-Beträgen abgeschrieben.

4 - nicht so sehr über die Datenbank an sich, aber in der Tat ärgerlich. Sich nicht um die Codequalität von SQL kümmern. Die Tatsache, dass Ihre SQL in Text ausgedrückt wird, macht es nicht in Ordnung, die Logik in Haufen von Algorithmen zur String-Manipulation zu verbergen. Es ist durchaus möglich, SQL in Text so zu schreiben, dass es von Ihren Programmierkollegen tatsächlich gelesen werden kann.

8
John Nilsson

Nicht das richtige Niveau von Normalisierung . Sie möchten sicherstellen, dass keine Daten dupliziert werden und dass Sie die Daten nach Bedarf in verschiedene aufteilen. Sie müssen auch sicherstellen, dass Sie die Normalisierung nicht zu verfolgen, da dies die Leistung beeinträchtigt.

8
Nathan Voxland
  • Ein ORM wie Hibernate aus Gründen wie "Es ist zu magisch" oder "Nicht in meiner Datenbank" aus dem Ruder laufen lassen.
  • Verlassen Sie sich zu sehr auf ein ORM wie Hibernate und versuchen Sie, es dort zu finden, wo es nicht angemessen ist.
8
Adam Jaskiewicz

Behandeln der Datenbank als nur einen Speichermechanismus (d. H. Eine verherrlichte Sammlungsbibliothek) und daher ihrer Anwendung untergeordnet (Ignorieren anderer Anwendungen, die die Daten gemeinsam nutzen)

8
finnw

Dies wurde bereits gesagt, aber: Indizes, Indizes, Indizes. Ich habe so viele Fälle von Unternehmens-Webanwendungen mit schlechter Leistung gesehen, die durch einfaches Erstellen eines Profils (um festzustellen, welche Tabellen häufig betroffen waren) und anschließendes Hinzufügen eines Index für diese Tabellen behoben wurden. Dies erfordert nicht einmal viel SQL-Schreibwissen, und die Auszahlung ist enorm.

Vermeiden Sie Datenvervielfältigungen wie die Pest. Einige Leute plädieren dafür, dass ein wenig Duplizieren nicht schadet und die Leistung verbessert. Hey, ich sage nicht, dass Sie Ihr Schema in die dritte Normalform quälen müssen, bis es so abstrakt ist, dass nicht einmal die DBAs wissen, was los ist. Wenn Sie einen Satz von Namen, Postleitzahlen oder Versandcodes duplizieren, werden die Kopien möglicherweise nicht mehr miteinander synchronisiert. Es wird passieren. Und dann machen Sie sich selbst fertig, während Sie das wöchentliche Wartungsskript ausführen.

Und zum Schluss: Verwenden Sie eine klare, konsistente und intuitive Namenskonvention. Genauso wie ein gut geschriebener Code lesbar sein sollte, sollte ein gutes SQL-Schema oder eine gute SQL-Abfrage lesbar sein und Ihnen praktisch sagen , was es tut. auch ohne kommentare. Sie werden sich in sechs Monaten bedanken, wenn Sie Wartungsarbeiten an den Tischen durchführen müssen. "SELECT account_number, billing_date FROM national_accounts" ist unendlich einfacher zu bedienen als "SELECT ACCNTNBR, BILLDAT FROM NTNLACCTS".

7
pbailey19

Keine entsprechende SELECT-Abfrage ausführen, bevor die DELETE-Abfrage ausgeführt wurde (insbesondere in Produktionsdatenbanken)!

6
Jamol

Der häufigste Fehler, den ich seit zwanzig Jahren gesehen habe: Nicht vorausplanen. Viele Entwickler erstellen eine Datenbank und Tabellen und ändern und erweitern die Tabellen kontinuierlich, während sie die Anwendungen erstellen. Das Endergebnis ist oft ein Chaos und ineffizient und später schwer zu bereinigen oder zu vereinfachen.

5
Skatterbrainz

a) Abfragewerte in Zeichenfolge fest codieren
b) Einfügen des Datenbankabfragecodes in die Aktion "OnButtonPress" in einer Windows Forms-Anwendung

Ich habe beides gesehen.

4
Benoit

Der Verwaltung von Datenbankverbindungen in Ihrer Anwendung wird nicht genügend Aufmerksamkeit geschenkt. Dann stellen Sie fest, dass die Anwendung, der Computer, der Server und das Netzwerk verstopft sind.

4
chefsmart
  1. Denken, dass sie DBAs und Datenmodellierer/Designer sind, wenn sie in diesen Bereichen keinerlei formale Belehrung haben.

  2. Zu denken, dass ihr Projekt keinen DBA erfordert, weil das alles einfach/trivial ist.

  3. Fehler beim Unterscheiden zwischen der in der Datenbank auszuführenden und der in der App auszuführenden Arbeit.

  4. Backups werden nicht validiert oder nicht gesichert.

  5. Einbetten von Raw SQL in ihren Code.

4
jonesy

Hier ist ein Link zu einem Video von Scott Walz mit dem Titel " Klassische Datenbankentwicklungsfehler und fünf Möglichkeiten, sie zu überwinden "

3
Charles Faiga
  1. Verwenden eines ORM für Massenupdates
  2. Auswahl von mehr Daten als benötigt. Auch dies erfolgt normalerweise bei Verwendung eines ORM
  3. SQLs in einer Schleife abfeuern.
  4. Keine guten Testdaten und Leistungsabfall nur bei Live-Daten.
3
Sriram

Kein Verständnis des Datenbank-Parallelitätsmodells und wie sich dies auf die Entwicklung auswirkt. Es ist einfach, Indizes und Tweak-Abfragen nachträglich hinzuzufügen. Anwendungen, die ohne angemessene Berücksichtigung von Hotspots, Ressourcenkonflikten und korrektem Betrieb entwickelt wurden (vorausgesetzt, dass das, was Sie gerade gelesen haben, noch gültig ist!), Können erhebliche Änderungen in der Datenbank und in der Anwendungsebene erfordern, um später korrigiert zu werden.

3
Einstein

Nun, ich muss sagen, dass der größte Fehler, den Anwendungsentwickler machen, darin besteht, die Datenbank nicht richtig zu normalisieren.

Als Anwendungsentwickler weiß ich, wie wichtig eine ordnungsgemäße Datenbankstruktur, -normalisierung und -wartung ist. Ich habe unzählige Stunden damit verbracht, mich über die Struktur und Verwaltung von Datenbanken zu informieren. Wenn ich mit einem anderen Entwickler zusammenarbeite, muss ich meiner Erfahrung nach in der Regel die gesamte Datenbank umstrukturieren und die App entsprechend aktualisieren, da sie in der Regel fehlerhaft ist und defekt.

Ich habe zum Beispiel angefangen, mit einem neuen Projekt zu arbeiten, bei dem der Entwickler mich gebeten hat, Facebook Connect auf der Website zu implementieren. Ich öffnete die Datenbank, um zu sehen, mit was ich arbeiten musste, und sah, dass jede kleine Information über einen bestimmten Benutzer in eine Tabelle gepackt war. Es Ich brauchte sechs Stunden, um ein Skript zu schreiben, das die Tabelle in vier oder fünf separate Tabellen aufteilte, und zwei weitere, um die App zu veranlassen, diese Tabellen zu verwenden. Bitte normalisieren Sie Ihre Datenbanken! Es wird alles andere weniger Kopfschmerzen machen.

3
Nick Anderegg

Ich verstehe nicht, wie ein DBMS unter der Haube funktioniert.

Sie können einen Stick nicht richtig fahren, ohne zu verstehen, wie eine Kupplung funktioniert. Und Sie können nicht verstehen, wie eine Datenbank verwendet wird, ohne zu verstehen, dass Sie wirklich nur in eine Datei auf Ihrer Festplatte schreiben.

Speziell:

  1. Wissen Sie, was ein Clustered Index ist? Haben Sie darüber nachgedacht, als Sie Ihr Schema entworfen haben?

  2. Wissen Sie, wie man Indizes richtig benutzt? Wie kann ich einen Index wiederverwenden? Wissen Sie, was ein Deckungsindex ist?

  3. So toll, Sie haben Indizes. Wie groß ist 1 Zeile in Ihrem Index? Wie groß wird der Index sein, wenn Sie viele Daten haben? Wird das leicht in Erinnerung bleiben? Wenn nicht, ist es als Index nutzlos.

  4. Haben Sie jemals EXPLAIN in MySQL verwendet? Toll. Jetzt sei ehrlich zu dir selbst: Hast du auch nur die Hälfte von dem verstanden, was du gesehen hast? Nein, hast du wahrscheinlich nicht. Repariere das.

  5. Verstehen Sie den Abfrage-Cache? Wissen Sie, warum eine Abfrage nicht zwischengespeichert werden kann?

  6. Verwenden Sie MyISAM? Wenn Sie eine Volltextsuche benötigen, ist MyISAM sowieso Mist. Verwenden Sie Sphinx. Dann wechseln Sie zu Inno.

3
Shane H

15 - Verwenden einer verrückten Konstruktions- und Anwendungslogik anstelle einer einfachen COALESCE.

2
jcampbell1
  • Sehr große Transaktionen, Einfügen/Aktualisieren vieler Daten und anschließendes Neuladen. Grundsätzlich ist dies darauf zurückzuführen, dass die Mehrbenutzerumgebung, in der die Datenbank arbeitet, nicht berücksichtigt wird.

  • Überbeanspruchung von Funktionen, insbesondere als Ergebnis von Selects und Where-Klauseln, die dazu führen, dass die Funktion für die Ergebnisse immer wieder aufgerufen wird. Ich denke, dies passt zu dem allgemeinen Fall, dass sie versuchen, in der prozeduralen Art und Weise zu arbeiten, wie sie es eher gewohnt sind, als SQL zu seinem vollen Vorteil zu nutzen.

2
Robin

Der größte Fehler besteht darin, eine Schleife im Code zu haben, in der Daten aktualisiert oder eingefügt werden, wenn eine einfache satzbasierte Lösung den Trick viel schneller und einfacher ausführen würde.

2
Test223345555

Ich denke, der größte Fehler, den alle Entwickler und Datenbankadministratoren machen, ist, zu viel an Konventionen zu glauben. Damit meine ich, dass Konventionen nur Richtlinien sind, die in den meisten Fällen funktionieren, aber nicht unbedingt immer. Ich bin ein gutes Beispiel für Normalisierung und Fremdschlüssel. Ich weiß, dass die meisten Leute dies nicht mögen, aber Normalisierung kann zu Komplexität und Leistungseinbußen führen. Wenn es also keinen Grund gibt, eine Telefonnummer in einen Telefontisch zu verschieben, sollten Sie dies nicht tun es. Auf den Fremdschlüsseln sind sie in den meisten Fällen großartig, aber wenn Sie versuchen, etwas zu erstellen, das bei Bedarf von sich aus funktioniert, wird der Fremdschlüssel in Zukunft ein Problem sein und Sie verlieren auch die Leistung. Wie auch immer, da ich traurige Regeln und Konventionen vorfinde, die immer beachtet, aber nicht unbedingt umgesetzt werden sollten, sollte immer eine Analyse jedes Einzelfalls durchgeführt werden.

2
Oakcool

Beschuldigen Sie die Datenbank-Engine, wenn die Abfrage, die auf Ihrem Entwicklungscomputer so schnell ausgeführt wurde, in die Luft sprengt und erstickt, wenn Sie etwas Verkehr auf die Anwendung werfen.

2
John Farrell

Viele Entwickler neigen dazu, mehrere Abfragen für die Datenbank auszuführen (häufig eine oder zwei Tabellen abfragend), die die Ergebnisse extrahieren und einfache Operationen in Java/c/c ++ ausführen - all dies hätte mit einer einzigen SQL-Anweisung erfolgen können.

Viele Entwickler stellen häufig nicht fest, dass sich Datenbank- und App-Server in Entwicklungsumgebungen auf ihren Laptops befinden. In einer Produktionsumgebung befinden sich Datenbank- und App-Server jedoch auf unterschiedlichen Computern. Daher gibt es für jede Abfrage einen zusätzlichen n/w-Aufwand für die Daten, die zwischen dem App-Server und dem Datenbankserver übertragen werden sollen. Ich war erstaunt, wie viele Datenbankaufrufe vom App-Server an den Datenbankserver vorgenommen wurden, um dem Benutzer eine Seite zu rendern!

2
sdc

Es gibt eine Sache, die ich hinzufügen könnte: Lernen Sie die Verwendung von Analysefunktionen wie PARTITION BY, RANK, DENSE_RANK (für Oracle). Sie sind für komplexe Abfragen unabdingbar.

Ein weiterer Rat ist, wenn möglich, einen dedizierten Datenbankentwickler in Ihrem Entwicklungsteam zu haben, der Experte für SQL, Datenbankmodellierung, -optimierung usw. ist (allerdings kein DBA). Eine solche Fähigkeit ist ein großer Vorteil.

1
softveda

Wenn Sie die Replikation (MySQL) verwenden, sind die folgenden Funktionen nur dann sicher, wenn Sie die zeilenbasierte Replikation verwenden.

USER(), CURRENT_USER() (or CURRENT_USER), UUID(), VERSION(), LOAD_FILE(), and Rand()

Siehe: http://dev.mysql.com/doc/refman/5.1/de/replication-features-functions.html

1
tszming

1) Schlechtes Verständnis für die ordnungsgemäße Interaktion zwischen Java und der Datenbank.

2) Über Parsing, unsachgemäße oder keine Wiederverwendung von SQL

3) BIND-Variablen werden nicht verwendet

4) Implementieren der prozeduralen Logik in Java), wenn die SQL-Set-Logik in der Datenbank funktioniert hätte (besser).

5) Keine angemessenen Leistungs- oder Skalierbarkeitstests vor Produktionsbeginn durchgeführt

6) Verwenden von Crystal Reports und nicht ordnungsgemäßes Festlegen des Schemanamens in den Berichten

7) Implementierung von SQL mit kartesischen Produkten, da der Ausführungsplan nicht bekannt ist (haben Sie sich sogar den EXPLAIN PLAN angesehen?)

1