Ich muss eine Abfrage schreiben, um eine große Liste von IDs abzurufen.
Wir unterstützen viele Backends (MySQL, Firebird, SQLServer, Oracle, PostgreSQL ...), daher muss ich ein Standard-SQL schreiben.
Die Größe des ID-Satzes könnte groß sein, die Abfrage würde programmgesteuert generiert. Was ist der beste Ansatz?
1) Schreiben einer Abfrage mit IN
SELECT * FROM TABLE WHERE ID IN (id1, id2, ..., idn)
Meine Frage hier ist. Was passiert, wenn n sehr groß ist? Und was ist mit der Leistung?
2) Schreiben einer Abfrage mit ODER
SELECT * FROM TABLE WHERE ID = id1 OR ID = id2 OR ... OR ID = idn
Ich denke, dass dieser Ansatz keine n-Grenze hat, aber was ist mit der Leistung, wenn n sehr groß ist?
3) Schreiben einer programmatischen Lösung:
foreach (var id in myIdList)
{
var item = GetItemByQuery("SELECT * FROM TABLE WHERE ID = " + id);
myObjectList.Add(item);
}
Bei diesem Ansatz sind einige Probleme aufgetreten, wenn der Datenbankserver über das Netzwerk abgefragt wird. Normalerweise ist es besser, eine Abfrage durchzuführen, bei der alle Ergebnisse abgerufen werden, als viele kleine Abfragen durchzuführen. Vielleicht bin ich falsch.
Was wäre eine richtige Lösung für dieses Problem?
IN
! Auf 80 ms ! Ich habe meine als Ihre Lösung 1 + 3 gemacht. Nur die letzte Abfrage war eine lange Abfragezeichenfolge, die zur Ausführung an SQL gesendet wurde.Antworten:
Option 1 ist die einzig gute Lösung.
Warum?
Option 2 macht dasselbe, aber Sie wiederholen den Spaltennamen viele Male. Außerdem weiß die SQL-Engine nicht sofort, dass Sie überprüfen möchten, ob der Wert einer der Werte in einer festen Liste ist. Eine gute SQL-Engine könnte sie jedoch optimieren, um die gleiche Leistung wie bei zu erzielen
IN
. Es gibt jedoch immer noch ein Problem mit der Lesbarkeit ...Option 3 ist in Bezug auf die Leistung einfach schrecklich. Es sendet jede Abfrage eine Abfrage und hämmert die Datenbank mit kleinen Abfragen. Es verhindert auch, dass Optimierungen für "Wert ist einer der Werte in einer bestimmten Liste" verwendet werden.
quelle
Ein alternativer Ansatz könnte darin bestehen, eine andere Tabelle zu verwenden, um ID-Werte zu enthalten. Diese andere Tabelle kann dann in Ihrer TABELLE innerlich verbunden werden, um zurückgegebene Zeilen einzuschränken. Dies hat den großen Vorteil, dass Sie kein dynamisches SQL benötigen (im besten Fall problematisch) und keine unendlich lange IN-Klausel haben.
Sie würden diese andere Tabelle abschneiden, Ihre große Anzahl von Zeilen einfügen und dann möglicherweise einen Index erstellen, um die Join-Leistung zu unterstützen. Außerdem können Sie die Anhäufung dieser Zeilen vom Abrufen von Daten trennen und möglicherweise mehr Optionen zum Optimieren der Leistung erhalten.
Update : Obwohl Sie eine temporäre Tabelle verwenden könnten, wollte ich nicht implizieren, dass Sie müssen oder sogar sollten. Eine permanente Tabelle, die für temporäre Daten verwendet wird, ist eine gängige Lösung mit Vorteilen, die über die hier beschriebenen hinausgehen.
quelle
select
Anweisung in einer anderen Tabelle abgerufen . Die Liste wird als die andere Tabelle übergeben,inner join
gegen die Sie antreten.Was Ed Guiness vorschlug, ist wirklich ein Leistungssteigerer. Ich hatte eine solche Anfrage
Was ich getan habe :
Dann verband Inner die Temperatur mit Haupttisch:
Und die Leistung hat sich drastisch verbessert.
quelle
Erste Option ist definitiv die beste Option.
Wenn man bedenkt, dass die Liste der IDs sehr groß ist , sagen wir Millionen, sollten Sie die folgenden Blockgrößen berücksichtigen:
Warum sollten Sie sich in Stücke teilen?
Für mich hat es immer wie ein Zauber gewirkt. Hoffe, es würde auch für meine Kollegen funktionieren :)
quelle
Das Ausführen des Befehls SELECT * FROM MyTable where id in () in einer Azure SQL-Tabelle mit 500 Millionen Datensätzen führte zu einer Wartezeit von> 7 Minuten!
Wenn Sie dies stattdessen tun, werden sofort Ergebnisse zurückgegeben:
Verwenden Sie einen Join.
quelle
In den meisten Datenbanksystemen werden
IN (val1, val2, …)
eine Reihe von SystemenOR
nach demselben Plan optimiert.Der dritte Weg wäre, die Liste der Werte in eine temporäre Tabelle zu importieren und sie zu verbinden, was in den meisten Systemen effizienter ist, wenn es viele Werte gibt.
Vielleicht möchten Sie diese Artikel lesen:
quelle
Beispiel 3 wäre der schlechteste von allen, da Sie die Datenbank unzählige Male ohne ersichtlichen Grund aufrufen.
Das Laden der Daten in eine temporäre Tabelle und das anschließende Verbinden wäre bei weitem am schnellsten. Danach sollte der IN etwas schneller arbeiten als die Gruppe der OPs.
quelle
Ich denke, Sie meinen SqlServer, aber unter Oracle haben Sie eine feste Grenze, wie viele IN-Elemente Sie angeben können: 1000.
quelle