Der Kern des Zitats der nicht vorzeitigen Optimierung besteht darin, einfachen und unkomplizierten Code zu verwenden und dann mit einem Profiler auf die Hotspots hinzuweisen, die Sie dann optimieren können, um effizient zu sein.
Wenn Sie select * verwenden, ist es unmöglich, ein Profil zu erstellen. Daher schreiben Sie keinen klaren und unkomplizierten Code und verstoßen gegen den Geist des Zitats. select *
ist ein Anti-Muster.
Die Auswahl von Spalten ist also keine vorzeitige Optimierung. Ein paar Dinge aus meinem Kopf ...
- Wenn Sie Spalten in einer SQL-Anweisung angeben, tritt bei der SQL-Ausführungsengine ein Fehler auf, wenn diese Spalte aus der Tabelle entfernt und die Abfrage ausgeführt wird.
- Sie können Code einfacher scannen, wenn diese Spalte verwendet wird.
- Sie sollten immer Abfragen schreiben, um die geringste Menge an Informationen zurückzubringen.
- Wie andere erwähnen, sollten Sie bei Verwendung des Ordnungsspaltenzugriffs niemals select * verwenden
- Wenn Ihre SQL-Anweisung Tabellen verbindet, erhalten Sie mit * alle Spalten aus allen Tabellen im Join
Die Konsequenz ist, dass mit select *
...
- Die von der Anwendung verwendeten Spalten sind undurchsichtig
- Datenbankadministratoren und ihre Abfrageprofiler können die schlechte Leistung Ihrer Anwendung nicht verbessern
- Der Code ist spröder, wenn Änderungen auftreten
- Ihre Datenbank und Ihr Netzwerk leiden darunter, dass sie zu viele Daten zurückbringen (E / A).
- Datenbankoptimierungen sind minimal, da Sie alle Daten unabhängig (logisch) zurückbringen.
Das Schreiben von korrektem SQL ist genauso einfach wie das Schreiben Select *
. Die wirklich faule Person schreibt also korrektes SQL, weil sie den Code nicht erneut aufrufen und versuchen möchte, sich daran zu erinnern, was sie getan haben, als sie es getan haben. Sie wollen den Datenbankadministratoren nicht jeden Code erklären. Sie wollen ihren Kunden nicht erklären, warum die Anwendung wie ein Hund läuft.
Wenn Ihr Code von den Spalten in einer bestimmten Reihenfolge abhängt, wird Ihr Code unterbrochen, wenn Änderungen an der Tabelle vorgenommen werden. Außerdem rufen Sie möglicherweise zu viel aus der Tabelle ab, wenn Sie * auswählen, insbesondere wenn die Tabelle ein Binärfeld enthält.
Nur weil Sie jetzt alle Spalten verwenden, bedeutet dies nicht, dass jemand anderes der Tabelle keine zusätzliche Spalte hinzufügen wird.
Es erhöht auch den Aufwand für das Zwischenspeichern der Planausführung, da die Metadaten über die Tabelle abgerufen werden müssen, um zu wissen, welche Spalten sich in * befinden.
quelle
Ein Hauptgrund ist, dass, wenn Sie jemals Spalten zu Ihrer Tabelle hinzufügen oder daraus entfernen, jede Abfrage / Prozedur, die einen SELECT * -Aufruf ausführt, jetzt mehr oder weniger Datenspalten als erwartet erhält.
quelle
Auf Umwegen brechen Sie die Modularitätsregel bezüglich der Verwendung strenger Eingaben, wo immer dies möglich ist. Explizit ist fast überall besser.
Selbst wenn Sie jetzt jede Spalte in der Tabelle benötigen, können später weitere hinzugefügt werden, die bei jeder Ausführung der Abfrage heruntergezogen werden und die Leistung beeinträchtigen können. Es schadet der Leistung, weil
Wann verwenden, wählen Sie *
Wenn Sie explizit jede Spalte in der Tabelle benötigen, anstatt jede Spalte in der Tabelle zu benötigen, die zu dem Zeitpunkt vorhanden war, als Sie die Abfrage geschrieben haben. Wenn Sie beispielsweise eine DB-Verwaltungs-App schreiben, die den gesamten Inhalt der Tabelle anzeigen muss (was auch immer sie sein mögen), können Sie diesen Ansatz verwenden.
quelle
SELECT *
wäre, wenn Sie Testabfragen mit dem DB-Client durchführen.Es gibt einige Gründe:
Hinweis: Ich habe im obigen Beispiel INTEGER gewählt, weil sie eine feste Größe von 4 Bytes haben.
quelle
Wenn Ihre Anwendung Daten mit SELECT * erhält und die Tabellenstruktur in der Datenbank geändert wird (z. B. wenn eine Spalte entfernt wird), schlägt Ihre Anwendung an jeder Stelle fehl, an der Sie auf das fehlende Feld verweisen. Wenn Sie stattdessen alle Spalten in Ihre Abfrage aufnehmen, wird Ihre Anwendung an der (hoffentlich) Stelle unterbrochen, an der Sie die Daten ursprünglich erhalten, was die Korrektur erleichtert.
Abgesehen davon gibt es eine Reihe von Situationen, in denen SELECT * wünschenswert ist. Eine Situation ist die, in der ich ständig eine ganze Tabelle in eine andere Datenbank replizieren muss (z. B. SQL Server auf DB2). Eine andere ist eine Anwendung, die geschrieben wurde, um Tabellen generisch anzuzeigen (dh ohne Kenntnis einer bestimmten Tabelle).
quelle
Ich habe tatsächlich ein seltsames Verhalten festgestellt, als ich es
select *
in Ansichten in SQL Server 2005 verwendet habe.Führen Sie die folgende Abfrage aus und Sie werden sehen, was ich meine.
Vergleichen Sie die Ergebnisse der letzten beiden select-Anweisungen. Ich glaube, Sie werden sehen, dass Select * Spalten nach Index anstelle des Namens referenziert.
Wenn Sie die Ansicht neu erstellen, funktioniert sie wieder einwandfrei.
BEARBEITEN
Ich habe eine separate Frage hinzugefügt: * "Aus Tabelle auswählen *" und "ColA, ColB usw. aus Tabelle auswählen". Interessantes Verhalten in SQL Server 2005 *, um dieses Verhalten genauer zu untersuchen.
quelle
Sie können zwei Tabellen verbinden und Spalte A aus der zweiten Tabelle verwenden. Wenn Sie später Spalte A zur ersten Tabelle hinzufügen (mit demselben Namen, aber möglicherweise unterschiedlicher Bedeutung), erhalten Sie höchstwahrscheinlich die Werte aus der ersten Tabelle und nicht aus der zweiten wie zuvor. Dies ist nicht der Fall, wenn Sie die Spalten, die Sie auswählen möchten, explizit angeben.
Natürlich führt die Angabe der Spalten manchmal auch zu Fehlern, wenn Sie vergessen, die neuen Spalten zu jeder Auswahlklausel hinzuzufügen. Wenn die neue Spalte nicht jedes Mal benötigt wird, wenn die Abfrage ausgeführt wird, kann es einige Zeit dauern, bis der Fehler bemerkt wird.
quelle
Ich verstehe, wohin Sie in Bezug auf vorzeitige Optimierung gehen, aber das geht wirklich nur bis zu einem gewissen Punkt. Ziel ist es, zu Beginn unnötige Optimierungen zu vermeiden . Sind Ihre Tabellen nicht indiziert? Würden Sie nvarchar (4000) verwenden, um eine Postleitzahl zu speichern?
Wie andere bereits betont haben, gibt es andere Vorteile bei der Angabe jeder Spalte, die Sie in der Abfrage verwenden möchten (z. B. Wartbarkeit).
quelle
Wenn Sie Spalten angeben, binden Sie sich auch in einen bestimmten Satz von Spalten ein und machen sich weniger flexibel, sodass Feuerstein überall einrollen kann. Nur ein Gedanke.
quelle
SELECT * ist nicht immer böse. Zumindest meiner Meinung nach. Ich verwende es ziemlich oft für dynamische Abfragen, die eine ganze Tabelle sowie einige berechnete Felder zurückgeben.
Zum Beispiel möchte ich geografische Geometrien aus einer "normalen" Tabelle berechnen, dh einer Tabelle ohne Geometriefeld, aber mit Feldern, die Koordinaten enthalten. Ich benutze postgresql und seine räumliche Erweiterung postgis. Das Prinzip gilt jedoch auch für viele andere Fälle.
Ein Beispiel:
eine Ortsübersicht mit Koordinaten in Feldern mit den Bezeichnungen x, y, z:
CREATE TABLE-Stellen (place_id-Ganzzahl, x-numerisch (10, 3), y-numerisch (10, 3), z-numerisch (10, 3), Beschreibung varchar);
Lassen Sie es uns mit ein paar Beispielwerten füttern:
INSERT INTO-Orte (place_id, x, y, z, Beschreibung) VALUES
(1, 2.295, 48.863, 64, 'Paris, Place de l \' Étoile '),
(2, 2.945, 48.858, 40,' Paris, Tour Eiffel '),
(3, 0,373, 43,958, 90,' Condom, Cathédrale St-Pierre ');
Ich möchte in der Lage sein, den Inhalt dieser Tabelle mit einem GIS-Client abzubilden. Der normale Weg besteht darin, der Tabelle ein Geometriefeld hinzuzufügen und die Geometrie basierend auf den Koordinaten zu erstellen. Ich würde es jedoch vorziehen, eine dynamische Abfrage zu erhalten: Wenn ich auf diese Weise Koordinaten ändere (Korrekturen, mehr Genauigkeit usw.), bewegen sich die zugeordneten Objekte tatsächlich dynamisch. Hier ist also die Abfrage mit dem SELECT * :
ANSICHT ERSTELLEN ODER ERSETZEN Orte_Punkte AS
SELECT *,
GeomFromewkt ('SRID = 4326; PUNKT (' || x || '' || y || '' || z || ')')
FROM Orte;
Informationen zur Verwendung der GeomFromewkt () -Funktion finden Sie unter postgis.
Hier ist das Ergebnis:
SELECT * FROM sites_points;
Die Spalte ganz rechts kann jetzt von jedem GIS-Programm verwendet werden, um die Punkte richtig abzubilden.
Ich wünschte, die Definition von VIEW könnte "wie sie ist" mit dem * beibehalten werden, aber hélas ist dies nicht der Fall: So wird es intern von postgresql gespeichert:
SELECT Orte.platz_ID, Orte.x, Orte.y, Orte.z, Orte.Beschreibung, Geomfromewkt (((((('SRID = 4326; POINT (43 :: Text || Orte.x)) ||' ': : text) || Orte.y) || '' :: Text) || Orte.z) || ')' :: Text) AS geomfromewkt FROM Orte;
quelle
Selbst wenn Sie jede Spalte verwenden, aber das Zeilenarray anhand eines numerischen Index adressieren, treten Probleme auf, wenn Sie später eine weitere Zeile hinzufügen.
Im Grunde ist es also eine Frage der Wartbarkeit! Wenn Sie den * Selektor nicht verwenden, müssen Sie sich nicht um Ihre Abfragen kümmern.
quelle
Wenn Sie nur die Spalten auswählen, die Sie benötigen, wird der Datensatz im Speicher kleiner und Ihre Anwendung schneller.
Außerdem speichern viele Tools (z. B. gespeicherte Prozeduren) Ausführungspläne für Abfragen. Wenn Sie später eine Spalte hinzufügen oder entfernen (besonders einfach, wenn Sie eine Ansicht auswählen), tritt häufig ein Fehler auf, wenn das erwartete Ergebnis nicht zurückgegeben wird.
quelle
Dies macht Ihren Code mehrdeutiger und schwieriger zu pflegen. weil Sie der Domain zusätzliche nicht verwendete Daten hinzufügen und nicht klar ist, welche Sie beabsichtigt haben und welche nicht. (Es deutet auch darauf hin, dass Sie es möglicherweise nicht wissen oder sich nicht darum kümmern.)
quelle
So beantworten Sie Ihre Frage direkt: Verwenden Sie "SELECT *" nicht, wenn Ihr Code dadurch anfälliger für Änderungen an den zugrunde liegenden Tabellen wird. Ihr Code sollte nur dann unterbrochen werden, wenn eine Änderung an der Tabelle vorgenommen wird, die sich direkt auf die Anforderungen Ihres Programms auswirkt.
Ihre Anwendung sollte die Abstraktionsschicht nutzen, die der relationale Zugriff bietet.
quelle
Ich benutze SELECT * nicht einfach, weil es schön ist zu sehen und zu wissen, welche Felder ich abrufe.
quelle
Im Allgemeinen ist es schlecht, 'select *' in Ansichten zu verwenden, da Sie gezwungen sind, die Ansicht im Falle einer Änderung der Tabellenspalte neu zu kompilieren. Wenn Sie die zugrunde liegenden Tabellenspalten einer Ansicht ändern, wird eine Fehlermeldung für nicht vorhandene Spalten angezeigt, bis Sie zurückgehen und neu kompilieren.
quelle
Es ist in Ordnung, wenn Sie dies tun,
exists(select * ...)
da es nie erweitert wird. Andernfalls ist es wirklich nur nützlich, wenn Sie Tabellen mit temporären Auswahlanweisungen untersuchen oder wenn Sie einen CTE oben definiert haben und jede Spalte möchten, ohne sie alle erneut einzugeben.quelle
Nur um eine Sache hinzuzufügen, die niemand sonst erwähnt hat.
Select *
Gibt alle Spalten zurück. Möglicherweise fügt jemand später eine Spalte hinzu, die die Benutzer nicht unbedingt sehen sollen, z. B. wer die Daten zuletzt aktualisiert hat, oder einen Zeitstempel oder Hinweise, die nur Manager nicht alle Benutzer sehen sollten.Wenn Sie eine Spalte hinzufügen, sollten Sie außerdem die Auswirkungen auf den vorhandenen Code überprüfen und prüfen, ob Änderungen erforderlich sind, basierend darauf, welche Informationen in der Spalte gespeichert sind. Bei Verwendung
select *
wird diese Überprüfung häufig übersprungen, da der Entwickler davon ausgeht, dass nichts kaputt geht. Tatsächlich scheint nichts explizit zu brechen, aber Abfragen geben möglicherweise das Falsche zurück. Nur weil nichts explizit kaputt geht, heißt das nicht, dass die Abfragen nicht geändert werden sollten.quelle
da "select *" Speicher verschwendet, wenn Sie nicht alle Felder benötigen. Bei SQL-Servern sind die Leistungen jedoch gleich.
quelle