In SQL Server 2012 (oder einer beliebigen Version ab 2005) ist die Verwendung SELECT *...
nur ein mögliches Leistungsproblem in der SELECT-Anweisung der obersten Ebene einer Abfrage.
Es ist also KEIN Problem in Views (*), in Unterabfragen, in EXIST-Klauseln, in CTEs oder in SELECT COUNT(*)..
usw. usw. Beachten Sie, dass dies wahrscheinlich auch für Oracle, DB2 und möglicherweise PostGres gilt (nicht sicher). , aber es ist sehr wahrscheinlich, dass es in vielen Fällen immer noch ein Problem für MySql ist.
Um zu verstehen, warum (und warum es in einem SELECT der obersten Ebene immer noch ein Problem sein kann), ist es hilfreich zu verstehen, warum es jemals ein Problem war, denn die Verwendung von SELECT *..
bedeutet " ALLE Spalten zurückgeben ". Im Allgemeinen werden dadurch viel mehr Daten zurückgegeben, als Sie wirklich möchten, was offensichtlich zu viel mehr E / A führen kann, sowohl auf der Festplatte als auch im Netzwerk.
Weniger offensichtlich ist, dass dies auch einschränkt, welche Indizes und Abfragepläne ein SQL-Optimierer verwenden kann, da er weiß, dass er letztendlich alle Datenspalten zurückgeben muss. Wenn das Unternehmen im Voraus weiß, dass Sie nur bestimmte Spalten benötigen, kann es häufig effizientere Abfragepläne verwenden, indem es Indizes nutzt, die nur diese Spalten enthalten. Glücklicherweise gibt es eine Möglichkeit, dies im Voraus zu wissen, dh Sie können die gewünschten Spalten in der Spaltenliste explizit angeben. Aber wenn Sie "*" verwenden, verzichten Sie zugunsten von "Geben Sie mir einfach alles, ich werde herausfinden, was ich brauche."
Ja, die Verarbeitung jeder Spalte erfordert zusätzlichen CPU- und Arbeitsspeicherbedarf, ist jedoch im Vergleich zu diesen beiden Faktoren fast immer geringfügig: die erhebliche zusätzliche Festplatten- und Netzwerkbandbreite, die für nicht benötigte Spalten erforderlich ist, und die Notwendigkeit, weniger zu verwenden optimierter Abfrageplan, da er jede Spalte enthalten muss.
Was hat sich also geändert? Grundsätzlich haben die SQL-Optimierer erfolgreich eine Funktion namens "Spaltenoptimierung" integriert, die nur bedeutet, dass sie jetzt in den Unterabfragen der unteren Ebene herausfinden können, ob Sie jemals tatsächlich eine Spalte in den oberen Ebenen der Abfrage verwenden werden.
Das Fazit ist, dass es keine Rolle mehr spielt, wenn Sie 'SELECT * ..' in den unteren / inneren Ebenen einer Abfrage verwenden. Entscheidend ist vielmehr, was sich in der Spaltenliste des SELECT der obersten Ebene befindet. Sofern Sie nicht SELECT *..
oben verwenden, muss erneut davon ausgegangen werden, dass ALLE Spalten gewünscht werden , und daher können Spaltenoptimierungen nicht effektiv eingesetzt werden.
(* - Beachten Sie, dass es in Views ein anderes, geringfügiges Bindungsproblem gibt, bei *
dem die Änderung in Spaltenlisten nicht immer registriert wird, wenn "*" verwendet wird. Es gibt andere Möglichkeiten, dies zu beheben, und dies wirkt sich nicht auf die Leistung aus.)
Es ist physisch und problematisch erlaubt
select * from table
, es ist jedoch eine schlechte Idee. Warum?Zunächst werden Sie feststellen, dass Sie Spalten zurückgeben, die Sie nicht benötigen (ressourcenintensiv).
Zweitens dauert es bei einer großen Tabelle länger als bei der Benennung der Spalten, da Sie bei Auswahl von * tatsächlich die Spaltennamen aus der Datenbank auswählen und sagen: "Geben Sie mir die Daten, die mit Spalten verknüpft sind, die Namen in dieser anderen Liste haben . " Während dies für den Programmierer schnell geht, können Sie sich vorstellen, dies auf dem Computer einer Bank zu tun, auf dem in einer Minute buchstäblich Hunderttausende von Suchvorgängen ausgeführt wurden.
Drittens wird es für den Entwickler schwieriger, dies zu tun. Wie oft müssen Sie von SSMS zu VS wechseln, um alle Spaltennamen abzurufen?
Viertens ist es ein Zeichen von Faulheit beim Programmieren, und ich glaube nicht, dass ein Entwickler diesen Ruf haben möchte.
quelle
Es kann ein Problem sein, wenn Sie den
Select * ...
Code in ein Programm einfügen, da sich die Datenbank, wie bereits erwähnt, im Laufe der Zeit möglicherweise ändert und mehr Spalten enthält, als Sie beim Schreiben der Abfrage erwartet hatten. Dies kann zu Programmfehlern führen (im besten Fall), oder das Programm geht auf eine fröhliche Art und Weise und beschädigt einige Daten, da es Feldwerte betrachtet, für die es nicht geschrieben wurde. Kurz gesagt, der Produktionscode sollte IMMER die Felder angeben, die im Feld zurückgegeben werden sollenSELECT
.Abgesehen davon habe ich weniger Probleme, wenn das
Select *
Teil einerEXISTS
Klausel ist, da alles, was an das Programm zurückgegeben wird, ein Boolescher Wert ist, der den Erfolg oder Misserfolg der Auswahl anzeigt. Andere mögen mit dieser Haltung nicht einverstanden sein, und ich respektiere ihre Meinung dazu. Der CodeSelect *
ist möglicherweise etwas weniger effizient als der Code für 'Select 1' in einerEXISTS
Klausel, aber ich glaube, es besteht in keiner Weise die Gefahr einer Datenbeschädigung.quelle
Viele Antworten, warum
select *
ist falsch, so werde ich abdecken, wenn ich das Gefühl habe, es ist richtig oder zumindest in Ordnung.1) In EXISTS wird der Inhalt des SELECT-Teils der Abfrage ignoriert, sodass Sie sogar schreiben können
SELECT 1/0
und kein Fehler auftritt .EXISTS
überprüft nur, dass einige Daten zurückkehren würden und gibt darauf basierend einen Booleschen Wert zurück.2) Dies könnte einen Feuersturm auslösen, aber ich verwende gerne
select *
Trigger in meiner Verlaufstabelle. Dadurchselect *
wird verhindert, dass die Haupttabelle eine neue Spalte erhält, ohne dass die Spalte auch der Verlaufstabelle hinzugefügt wird, da ein Fehler sofort beim Einfügen / Aktualisieren / Löschen in die Haupttabelle auftritt. Dies hat mehrfach verhindert, dass Entwickler Spalten hinzufügten und vergaßen, sie der Verlaufstabelle hinzuzufügen.quelle
SELECT 1
es immer noch, weil es am offensichtlichsten zukünftige Code-Betreuer über Ihre Absicht informiert. Es ist keine Voraussetzung , aber wenn ich es sehe... WHERE EXISTS (SELECT 1 ...)
, kündigt es sich ganz offensichtlich als Wahrheitstest an.SELECT 1
basierend auf einem Mythos, dass Leistung besser wäre alsSELECT *
. Beide Optionen sind jedoch durchaus akzeptabel. Aufgrund der Art und Weise, wie der Optimierer mit EXISTS umgeht, gibt es keine Leistungsunterschiede. Auch kein Unterschied in der Lesbarkeit aufgrund des Wortes "EXISTS", das eindeutig einen Wahrheitstest ankündigt.Column8
der Haupttabelle hinzu und vergisst die Verlaufstabelle. Entwickler schreibt eine Reihe von Code in Spalte 8. Dann fügtColumn9
er der Haupttabelle hinzu; diesmal daran denken, auch zur Geschichte beizutragen. Beim späteren Testen merkt er, dass er vergessen hat,Column9
der Historie etwas hinzuzufügen (dank Ihrer Fehlererkennungstechnik), und fügt es sofort hinzu. Jetzt scheint der Trigger zu funktionieren, aber die Daten in den Spalten 8 und 9 sind im Verlauf vertauscht. : S