Warum
SELECT Barraportfolioname
FROM portfolio
WHERE id IN (SELECT DISTINCT i1.portfolioid
FROM Import i1
LEFT OUTER JOIN Import i2
ON i1.PortfolioID = i2.PortfolioID
AND i2.ImportSetID = 82
WHERE i1.ImportSetID = 83
AND i2.ID IS NULL)
dauert 0 Sekunden, während die folgende Abfrage 5 Sekunden dauert.
SELECT DISTINCT p.BarraPortfolioName AS name
FROM Import i1
INNER JOIN Portfolio p
ON p.ID = i1.PortfolioID
LEFT OUTER JOIN Import i2
ON i1.PortfolioID = i2.PortfolioID
AND i2.ImportSetID = 82
WHERE i1.ImportSetID = 83
AND i2.ID IS NULL;
Ich benutze SQL Server. Beide Tabellen haben Indizes für alle Spalten, die in der Abfrage verwendet werden, dh Portfolio-ID, ID, Import-ID.
Bearbeiten von gbn, basierend auf OP-Kommentar
Sie sagten:
Dies funktioniert viel besser als die beiden vorherigen Abfragen.
select
BarraPortfolioName
from
(
select distinct p.BarraPortfolioName,portfolioid
from
import i1
inner join
portfolio p on p.id=i1.portfolioid
where
importsetid = ?
) as p1
left outer join
(
select distinct portfolioid
from import
where importsetid = ?
) as p2 on p1.portfolioid = p2.portfolioid
where
p2.portfolioid is null
sql-server
performance
query
techExplorer
quelle
quelle
Antworten:
Dies setzt voraus, dass beide die gleichen Ergebnisse liefern
Die erste ist eine "Semi-Verknüpfung" aufgrund der IN (Unterabfrage) (die DISTINCT wird nicht benötigt).
Dies bedeutet, dass die Unterabfrage "kurzschließen" kann.
Die zweite ist eine äußere Verknüpfung und dann eine Einschränkung, gefolgt von einem DISTINCT-Aggregat.
Dies sind 3 diskrete Hauptoperationen
Dieser "Kurzschluss" ist der Hauptgrund für den Unterschied, selbst bei der äußeren Verknüpfung in der Unterabfrage.
Für einfachere Abfragen würde die 2. Abfrage auf den gleichen Plan wie die 1. optimiert, da sie semantisch identisch ist. Je später die Version usw.
Weitere Informationen finden Sie hier (gleiche Logik, nur umgekehrt): Die Verwendung der NOT-Logik in Bezug auf Indizes
Und dies über "IN vs. JOIN vs. EXISTS" von SO-Benutzer Quassnoi auf seiner Website
Und ein ähnliches SO-Beispiel: https://stackoverflow.com/a/7221395/27535
quelle
Probieren Sie es aus mit:
Sie möchten lediglich die eindeutigen i1.PortfolioIDs suchen, diese Liste nach solchen filtern, die nicht in Importset 82 enthalten waren, und den Namen für diese IDs anzeigen.
quelle
Wenn Sie keinen eindeutigen Index für BarraPortfolioName haben, müssen alle auf Duplikate überprüft werden. Dies ist in der ersten Abfrage nicht erforderlich, da Ihre IN-Klausel dies für Sie erledigt.
Versuchen Sie, einen eindeutigen Index (oder eine eindeutige Einschränkung) zu erstellen, und prüfen Sie, ob dies der Trick ist. Oder ändern Sie das zweite Skript, indem Sie das eindeutige Skript löschen und
GROUP BY p.id, p.BarraPortfolioName
am Ende setzen. Dies sollte es ermöglichen, den Unterscheidungsprozess kurzzuschließen.quelle
GROUP BY
Jetzt meinen . Ich dachte, das würde die Semantik ändern, aber wenn sieBarraPortfolioName
nicht eindeutig ist, unterscheiden sich die beiden Abfragen im OP ohnehin semantisch, da die erste ebenfallsDISTINCT
hinzugefügt werden müsste . Beim Testen stelle ich immer noch fest, dass Abfrage 1 einen Semi-Join verwendet und Abfrage 2 jedoch nicht, sodass das OP nur bei 1 IMO bleiben sollte.