Ich habe gehört, dass dies SELECT *
beim Schreiben von SQL-Befehlen im Allgemeinen eine schlechte Praxis ist, da es für SELECT
Spalten, die Sie speziell benötigen, effizienter ist .
Wenn ich zu SELECT
jeder Spalte in einer Tabelle muss, sollte ich verwenden
SELECT * FROM TABLE
oder
SELECT column1, colum2, column3, etc. FROM TABLE
Ist die Effizienz in diesem Fall wirklich wichtig? Ich würde denken SELECT *
, dass es intern optimaler wäre, wenn Sie wirklich alle Daten benötigen, aber ich sage dies ohne wirkliches Verständnis der Datenbank.
Ich bin gespannt, was in diesem Fall die beste Vorgehensweise ist.
UPDATE: Ich sollte wahrscheinlich angeben, dass die einzige Situation, in der ich wirklich etwas tun möchte , darin SELECT *
besteht, Daten aus einer Tabelle auszuwählen, in der ich weiß, dass alle Spalten immer abgerufen werden müssen, auch wenn neue Spalten hinzugefügt werden.
Angesichts der Antworten, die ich gesehen habe, scheint dies jedoch immer noch eine schlechte Idee zu sein und SELECT *
sollte niemals aus viel mehr technischen Gründen verwendet werden, über die ich jemals nachgedacht habe.
Antworten:
Ein Grund dafür, dass die Auswahl bestimmter Spalten besser ist, besteht darin, dass die Wahrscheinlichkeit erhöht wird, dass SQL Server über Indizes auf die Daten zugreifen kann, anstatt die Tabellendaten abzufragen.
Hier ist ein Beitrag, den ich darüber geschrieben habe: Der wahre Grund für ausgewählte Abfragen ist eine schlechte Indexabdeckung
Änderungen sind auch weniger fragil, da jeder Code, der die Daten verbraucht, unabhängig von Änderungen, die Sie in Zukunft am Tabellenschema vornehmen, dieselbe Datenstruktur erhält.
quelle
vs
all_column_names), während wir Tausende von Zeilen haben und SELECT mit Index ausführen (in der WHERE-Klausel)?In Anbetracht Ihrer Spezifikation , dass Sie werden alle Spalten der Auswahl gibt es kaum einen Unterschied zu diesem Zeitpunkt . Beachten Sie jedoch, dass sich Datenbankschemata ändern. Wenn Sie verwenden
SELECT *
, werden der Tabelle neue Spalten hinzugefügt, obwohl Ihr Code aller Wahrscheinlichkeit nach nicht bereit ist, diese neuen Daten zu verwenden oder zu präsentieren. Dies bedeutet, dass Sie Ihr System unerwarteten Leistungs- und Funktionsänderungen aussetzen.Sie sind möglicherweise bereit, dies als geringfügige Kosten abzutun, stellen jedoch fest, dass Spalten, die Sie noch nicht benötigen, Folgendes sein müssen:
Artikel 1 hat viele versteckte Kosten, einschließlich der Eliminierung eines potenziellen Deckungsindex, der das Laden von Datenseiten (und das Thrashing des Server-Cache) und das Sperren von Zeilen / Seiten / Tabellen verursacht, die andernfalls vermieden werden könnten.
Vergleichen Sie dies mit den potenziellen Einsparungen bei der Angabe der Spalten im Vergleich zu an.
*
Die einzigen potenziellen Einsparungen sind:Für Punkt 1 ist die Realität, dass Sie Code hinzufügen / ändern, um jede neue Spalte zu verwenden, die Sie ohnehin hinzufügen könnten. Es handelt sich also um eine Wäsche.
Bei Punkt 2 reicht der Unterschied selten aus, um Sie in eine andere Paketgröße oder Anzahl von Netzwerkpaketen zu verschieben. Wenn Sie an einem Punkt angelangt sind, an dem die Übertragungszeit von SQL-Anweisungen das vorherrschende Problem ist, müssen Sie wahrscheinlich zuerst die Rate der Anweisungen reduzieren.
Für Punkt 3 gibt es KEINE Einsparungen, da die Erweiterung
*
ohnehin erfolgen muss, was bedeutet, dass das Schema der Tabelle (n) trotzdem konsultiert wird. Realistisch gesehen verursacht das Auflisten der Spalten die gleichen Kosten, da sie anhand des Schemas validiert werden müssen. Mit anderen Worten, dies ist eine vollständige Wäsche.Wenn Sie für Punkt 4 bestimmte Spalten angeben, wird der Abfrageplan-Cache möglicherweise größer, jedoch nur, wenn Sie mit verschiedenen Spaltengruppen arbeiten (was nicht von Ihnen angegeben wurde). In diesem Fall möchten Sie unterschiedliche Cache-Einträge, da Sie nach Bedarf unterschiedliche Pläne wünschen.
Dies alles hängt aufgrund der Art und Weise, wie Sie die Frage angegeben haben, von der Ausfallsicherheit des Problems angesichts eventueller Schemaänderungen ab. Wenn Sie dieses Schema in ein ROM brennen (es passiert), ist ein
*
durchaus akzeptabel.Meine allgemeine Richtlinie lautet jedoch, dass Sie nur die Spalten auswählen sollten, die Sie benötigen. Dies bedeutet, dass es manchmal so aussieht, als würden Sie nach allen fragen. DBAs und die Schemaentwicklung bedeuten jedoch, dass möglicherweise einige neue Spalten angezeigt werden, die die Abfrage stark beeinflussen können .
Mein Rat ist, dass Sie IMMER bestimmte Spalten AUSWÄHLEN sollten . Denken Sie daran, dass Sie immer wieder gut darin sind, was Sie tun. Gewöhnen Sie sich also einfach an, es richtig zu machen.
Wenn Sie sich fragen, warum sich ein Schema möglicherweise ändert, ohne dass sich der Code ändert, denken Sie an die Überwachungsprotokollierung, die Gültigkeits- / Ablaufdaten und andere ähnliche Dinge, die von DBAs systematisch für Compliance-Probleme hinzugefügt werden. Eine weitere Ursache für hinterhältige Änderungen sind Denormalisierungen für die Leistung an anderer Stelle im System oder in benutzerdefinierten Feldern.
quelle
Sie sollten nur die Spalten auswählen, die Sie benötigen. Selbst wenn Sie alle Spalten benötigen, ist es immer noch besser, Spaltennamen aufzulisten, damit der SQL Server die Systemtabelle nicht nach Spalten abfragen muss.
Außerdem kann Ihre Anwendung unterbrochen werden, wenn jemand der Tabelle Spalten hinzufügt. Ihr Programm erhält Spalten, die es nicht erwartet hat, und es weiß möglicherweise nicht, wie es verarbeitet werden soll.
Abgesehen davon, wenn die Tabelle eine Binärspalte enthält, ist die Abfrage viel langsamer und verwendet mehr Netzwerkressourcen.
quelle
Es gibt vier große Gründe, die
select *
schlecht sind:Der wichtigste praktische Grund ist, dass der Benutzer gezwungen ist, die Reihenfolge, in der die Spalten zurückgegeben werden, auf magische Weise zu kennen. Es ist besser, explizit zu sein, was Sie auch vor dem Tischwechsel schützt, der sich gut in ...
Wenn sich ein Spaltenname, den Sie verwenden, ändert, ist es besser, ihn frühzeitig (zum Zeitpunkt des SQL-Aufrufs) abzufangen, als wenn Sie versuchen, die Spalte zu verwenden, die nicht mehr vorhanden ist (oder deren Name geändert wurde usw.). )
Durch das Auflisten der Spaltennamen wird Ihr Code weitaus selbstdokumentierter und daher wahrscheinlich besser lesbar.
Wenn Sie über ein Netzwerk übertragen (oder auch nicht), sind Spalten, die Sie nicht benötigen, nur Verschwendung.
quelle
*
in eine Reihe von Namen ändern können .)Das Angeben der Spaltenliste ist normalerweise die beste Option, da Ihre Anwendung nicht betroffen ist, wenn jemand eine Spalte zur Tabelle hinzufügt / einfügt.
quelle
Das Angeben von Spaltennamen ist definitiv schneller - für den Server. Aber falls
Dann bleiben Sie besser bei SELECT *. In unserem Framework können wir durch die häufige Verwendung von SELECT * ein neues, von der Website verwaltetes Inhaltsfeld in eine Tabelle einfügen, das alle Vorteile des CMS (Versionierung, Workflow / Genehmigungen usw.) bietet, während wir nur den Code bei a berühren ein paar Punkte statt ein paar Dutzend Punkte.
Ich weiß, dass die DB-Gurus mich dafür hassen werden - machen Sie weiter, stimmen Sie mich ab -, aber in meiner Welt ist die Entwicklerzeit knapp und die CPU-Zyklen sind reichlich vorhanden. Deshalb passe ich entsprechend an, was ich konserviere und was ich verschwende.
quelle
SELECT * ist eine schlechte Praxis, auch wenn die Abfrage nicht über ein Netzwerk gesendet wird.
Natürlich ist das alles für ein kleines und einfaches System nicht wichtig.
quelle
In Bezug auf die Leistung kann SELECT mit bestimmten Spalten schneller sein (es müssen nicht alle Daten eingelesen werden). Wenn Ihre Abfrage wirklich ALLE Spalten verwendet, wird SELECT mit expliziten Parametern weiterhin bevorzugt. Jeder Geschwindigkeitsunterschied ist grundsätzlich unbemerkt und nahezu zeitkonstant. Eines Tages wird sich Ihr Schema ändern, und dies ist eine gute Versicherung, um Probleme aufgrund dieser zu vermeiden.
quelle
Viele gute Gründe haben hier bisher geantwortet, hier ist ein weiterer, der nicht erwähnt wurde.
Die explizite Benennung der Spalten hilft Ihnen bei der späteren Wartung. Irgendwann werden Sie Änderungen vornehmen oder Fehler beheben und sich fragen: "Wo zum Teufel wird diese Spalte verwendet?".
Wenn Sie die Namen explizit aufgelistet haben, ist es einfach, jeden Verweis auf diese Spalte - über alle Ihre gespeicherten Prozeduren, Ansichten usw. - zu finden. Speichern Sie einfach ein CREATE-Skript für Ihr DB-Schema und durchsuchen Sie es mit Text.
quelle
Definieren Sie die Spalten definitiv, da SQL Server die Spalten nicht nachschlagen muss, um sie abzurufen. Wenn Sie die Spalten definieren, kann SQL diesen Schritt überspringen.
quelle
Es ist immer besser, die Spalten anzugeben, die Sie benötigen. Wenn Sie einmal darüber nachdenken, muss SQL nicht bei jeder Abfrage an "wtf is *" denken. Darüber hinaus kann später jemand der Tabelle Spalten hinzufügen, die Sie in Ihrer Abfrage tatsächlich nicht benötigen. In diesem Fall sind Sie besser dran, wenn Sie alle Ihre Spalten angeben.
quelle
Das Problem mit "select *" ist die Möglichkeit, Daten zu bringen, die Sie nicht wirklich benötigen. Während der eigentlichen Datenbankabfrage tragen die ausgewählten Spalten nicht wirklich zur Berechnung bei. Was wirklich "schwer" ist, ist der Datentransport zurück zu Ihrem Client. Jede Spalte, die Sie nicht wirklich benötigen, verschwendet nur die Netzwerkbandbreite und verlängert die Zeit, die Sie auf die Rückgabe Ihrer Abfrage warten.
Selbst wenn Sie alle Spalten verwenden, die aus einem "select * ..." stammen, ist dies nur für den Moment. Wenn Sie in Zukunft das Tabellen- / Ansichtslayout ändern und weitere Spalten hinzufügen, werden diese in Ihre Auswahl aufgenommen, auch wenn Sie sie nicht benötigen.
Ein weiterer Punkt, an dem eine "select *" - Anweisung schlecht ist, ist die Erstellung von Ansichten. Wenn Sie eine Ansicht mit "select *" erstellen und später Spalten zu Ihrer Tabelle hinzufügen, stimmen die Ansichtsdefinition und die zurückgegebenen Daten nicht überein, und Sie müssen Ihre Ansichten neu kompilieren, damit sie wieder funktionieren.
Ich weiß, dass das Schreiben eines "select *" verlockend ist, weil ich wirklich nicht gerne alle Felder in meinen Abfragen manuell spezifiziere, aber wenn sich Ihr System weiterentwickelt, werden Sie feststellen, dass es sich lohnt, diese zusätzliche Zeit zu verbringen / Aufwand bei der Angabe der Felder, anstatt viel mehr Zeit und Mühe damit zu verbringen, Fehler in Ihren Ansichten zu beseitigen oder Ihre App zu optimieren.
quelle
Während das explizite Auflisten von Spalten gut für die Leistung ist, sollten Sie nicht verrückt werden.
Wenn Sie also alle Daten verwenden, versuchen Sie es der Einfachheit halber mit SELECT * (stellen Sie sich vor, Sie haben viele Spalten und führen eine JOIN ... -Abfrage durch, die möglicherweise schrecklich wird). Dann - messen. Vergleichen Sie mit der Abfrage mit explizit aufgeführten Spaltennamen.
Spekulieren Sie nicht über Leistung, messen Sie sie!
Die explizite Auflistung ist am hilfreichsten, wenn Sie eine Spalte mit großen Datenmengen (z. B. Text eines Beitrags oder Artikels) haben und diese in einer bestimmten Abfrage nicht benötigen. Wenn Sie es dann nicht in Ihrer Antwort zurückgeben, kann der DB-Server Zeit, Bandbreite und Festplattendurchsatz sparen. Ihr Abfrageergebnis ist auch kleiner, was für jeden Abfragecache gut ist.
quelle
Sie sollten wirklich nur die Felder auswählen, die Sie benötigen, und nur die erforderliche Anzahl, dh
Außerhalb der Datenbank besteht bei dynamischen Abfragen das Risiko von Injektionsangriffen und fehlerhaften Daten. In der Regel umgehen Sie dies mithilfe gespeicherter Prozeduren oder parametrisierter Abfragen. Außerdem muss der Server (obwohl nicht wirklich ein großes Problem) jedes Mal, wenn eine dynamische Abfrage ausgeführt wird, einen Ausführungsplan erstellen.
quelle
Die Auswahl ist gleichermaßen effizient (in Bezug auf die Geschwindigkeit), wenn Sie * oder Spalten verwenden.
Der Unterschied liegt im Gedächtnis, nicht in der Geschwindigkeit. Wenn Sie mehrere Spalten auswählen, muss SQL Server Speicherplatz für die Abfrage zuweisen, einschließlich aller Daten für alle von Ihnen angeforderten Spalten, auch wenn Sie nur eine davon verwenden.
Was für die Leistung wichtig ist, ist der Ausführungsplan, der wiederum stark von Ihrer WHERE-Klausel und der Anzahl der JOIN, OUTER JOIN usw. abhängt.
Verwenden Sie für Ihre Frage einfach SELECT *. Wenn Sie alle Spalten benötigen, gibt es keinen Leistungsunterschied.
quelle
Es ist NICHT schneller, explizite Feldnamen im Vergleich zu * zu verwenden, wenn und nur dann, wenn Sie die Daten für alle Felder abrufen müssen.
Ihre Client-Software sollte nicht von der Reihenfolge der zurückgegebenen Felder abhängen, das ist also auch ein Unsinn.
Und es ist möglich (wenn auch unwahrscheinlich), dass Sie alle Felder mit * abrufen müssen, da Sie noch nicht wissen, welche Felder vorhanden sind (denken Sie an eine sehr dynamische Datenbankstruktur).
Ein weiterer Nachteil der Verwendung expliziter Feldnamen besteht darin, dass das Lesen des Codes und / oder des Abfrageprotokolls schwieriger wird, wenn viele davon vorhanden und lang sind.
Die Regel sollte also lauten: Wenn Sie alle Felder benötigen, verwenden Sie *. Wenn Sie nur eine Teilmenge benötigen, benennen Sie sie explizit.
quelle
Das Ergebnis ist zu groß. Es ist langsam, das Ergebnis von der SQL-Engine zu generieren und an den Client zu senden.
Die Client-Seite ist eine generische Programmierumgebung und sollte und sollte nicht zum Filtern und Verarbeiten der Ergebnisse (z. B. WHERE-Klausel, ORDER-Klausel) ausgelegt sein, da die Anzahl der Zeilen sehr groß sein kann (z. B. mehrere zehn Millionen Zeilen).
quelle
Durch das Benennen jeder Spalte, die Sie in Ihrer Anwendung erwarten, wird auch sichergestellt, dass Ihre Anwendung nicht beschädigt wird, wenn jemand die Tabelle ändert, solange Ihre Spalten noch vorhanden sind (in beliebiger Reihenfolge).
quelle
Dies hängt von der Version Ihres DB-Servers ab, aber moderne Versionen von SQL können den Plan in beiden Fällen zwischenspeichern. Ich würde sagen, gehen Sie mit dem, was mit Ihrem Datenzugriffscode am wartbarsten ist.
quelle
Ein Grund, warum es besser ist, genau anzugeben, welche Spalten Sie möchten, sind mögliche zukünftige Änderungen in der Tabellenstruktur.
Wenn Sie Daten manuell mithilfe eines indexbasierten Ansatzes einlesen, um eine Datenstruktur mit den Ergebnissen Ihrer Abfrage zu füllen, werden Sie in Zukunft beim Hinzufügen / Entfernen einer Spalte Kopfschmerzen haben, um herauszufinden, was schief gelaufen ist.
Was schneller ist, werde ich anderen wegen ihres Fachwissens aufschieben.
quelle
Wie bei den meisten Problemen hängt es davon ab, was Sie erreichen möchten. Wenn Sie ein Datenbankraster erstellen möchten, das alle Spalten in einer Tabelle zulässt, ist "Select *" die Antwort. Wenn Sie jedoch nur bestimmte Spalten benötigen und das Hinzufügen oder Löschen von Spalten zur Abfrage nur selten erfolgt, geben Sie diese einzeln an.
Dies hängt auch von der Datenmenge ab, die Sie vom Server übertragen möchten. Wenn eine der Spalten als Memo, Grafik, Blob usw. definiert ist und Sie diese Spalte nicht benötigen, verwenden Sie besser nicht "Auswählen *", da Sie sonst eine ganze Reihe von Daten erhalten, die Sie nicht benötigen wollen und Ihre Leistung könnte leiden.
quelle
Wenn alle von Ihnen ausgewählten Spalten in einem Index enthalten sind, wird Ihre Ergebnismenge aus dem Index abgerufen, anstatt zusätzliche Daten aus SQL nachzuschlagen.
quelle
SELECT * ist erforderlich, wenn Metadaten wie die Anzahl der Spalten abgerufen werden sollen.
quelle
Was alle oben gesagt haben, plus:
Wenn Sie nach lesbarem, wartbarem Code streben, gehen Sie wie folgt vor:
SELECT foo, bar FROM Widgets;
ist sofort lesbar und zeigt Absicht. Wenn Sie diesen Anruf tätigen, wissen Sie, was Sie zurückbekommen. Wenn Widgets nur Foo- und Balkenspalten haben, bedeutet die Auswahl von *, dass Sie immer noch darüber nachdenken müssen, was Sie zurückerhalten, bestätigen, dass die Reihenfolge korrekt zugeordnet ist usw. Wenn Widgets jedoch mehr Spalten haben, Sie aber nur an Foo interessiert sind und bar, dann wird Ihr Code unordentlich, wenn Sie nach einem Platzhalter fragen und dann nur einen Teil der zurückgegebenen Daten verwenden.
quelle
Und denken Sie daran, wenn Sie per Definition einen inneren Join haben, benötigen Sie nicht alle Spalten, da die Daten in den Join-Spalten wiederholt werden.
Es ist nicht so, dass das Auflisten von Spalten im SQl-Server schwierig oder sogar zeitaufwändig ist. Sie ziehen sie einfach aus dem Objektbrowser (Sie können alles auf einmal erhalten, indem Sie aus den Wortspalten ziehen). Ein dauerhafter Leistungseinbruch auf Ihrem System (da dies die Verwendung von Indizes reduzieren kann und das Senden nicht benötigter Daten über das Netzwerk kostspielig ist) und die Wahrscheinlichkeit erhöhen, dass Sie unerwartete Probleme haben, wenn sich die Datenbank ändert (manchmal werden Spalten hinzugefügt) Sie möchten nicht, dass der Benutzer zum Beispiel sieht.) Nur weniger als eine Minute Entwicklungszeit zu sparen, ist kurzsichtig und unprofessionell.
quelle
In Bezug auf die Leistung habe ich Kommentare gesehen, dass beide gleich sind. Aber Usability-Aspekt gibt es einige + und s
Wenn Sie in einer Abfrage ein (select *) verwenden und jemand die Tabelle ändert und neue Felder hinzufügt, die für die vorherige Abfrage nicht benötigt werden, ist dies ein unnötiger Overhead. Und was ist, wenn das neu hinzugefügte Feld ein Blob oder ein Bildfeld ist? Ihre Antwortzeit auf Anfragen wird dann sehr langsam sein.
Wenn Sie dagegen a (select col1, col2, ..) verwenden und wenn die Tabelle geändert und neue Felder hinzugefügt werden und wenn diese Felder in der Ergebnismenge benötigt werden, müssen Sie Ihre select-Abfrage nach der Tabellenänderung immer bearbeiten.
Ich empfehle jedoch, in Ihren Abfragen immer select col1, col2, ... zu verwenden und die Abfrage zu ändern, wenn die Tabelle später geändert wird ...
quelle
Definieren Sie unbedingt die Spalten, die Sie jedes Mal auswählen möchten. Es gibt keinen Grund, dies nicht zu tun, und die Leistungsverbesserung ist es wert.
Sie hätten niemals die Option "SELECT *" geben dürfen.
quelle
Wenn Sie jede Spalte benötigen, verwenden Sie einfach SELECT *. Beachten Sie jedoch, dass sich die Reihenfolge möglicherweise ändern kann. Wenn Sie die Ergebnisse verbrauchen, greifen Sie nach Namen und nicht nach Index zu.
Ich würde Kommentare darüber ignorieren, wie * die Liste abrufen muss - die Wahrscheinlichkeit, dass benannte Spalten analysiert und validiert werden, entspricht der Verarbeitungszeit, wenn nicht mehr. Nicht vorzeitig optimieren ;-)
quelle
In Bezug auf die Ausführungseffizienz sind mir keine signifikanten Unterschiede bekannt. Aber für die Effizienz der Programmierer würde ich die Namen der Felder schreiben, weil
quelle
Hey, sei praktisch. Verwenden Sie beim Prototyping select * und beim Implementieren und Bereitstellen bestimmte Spalten. Aus Sicht des Ausführungsplans sind beide auf modernen Systemen relativ identisch. Durch die Auswahl bestimmter Spalten wird jedoch die Datenmenge begrenzt, die von der Festplatte abgerufen, im Speicher gespeichert und über das Netzwerk gesendet werden muss.
Letztendlich ist es am besten, bestimmte Spalten auszuwählen.
quelle