Information ausblenden
Willkommen im Forum für alle Datenbanken! Registriere Dich kostenlos und diskutiere über DBs wie Mysql, MariaDB, Oracle, Sql-Server, Postgres, Access uvm

Warum EXISTS anstatt IN?

Dieses Thema im Forum "Allgemeine Diskussionen" wurde erstellt von PLSQL_SQL, 3 Mai 2012.

  1. PLSQL_SQL

    PLSQL_SQL Datenbank-Guru

    Diese Frage ist anhand eines Beispiels am besten erklärt!

    Example - IN:
    Code:
    select *
        from tabelle1 t1
        where t1.spalte1 IN ( select t2.spalte1 from tabelle2 t2 )
    
    Diese liefert ALLE Datensätze von Tabelle1, wo die Spalte1 von Tabelle1 GLEICH der Spalte1 von Tabelle2 ist. (Tabelle1.Spalte1 = Tabelle2.Spalte1)

    Jedoch wird für JEDEN Datensatz des äußeren Select-Stmt der Subselect in der where - Klause ausgeführt. Dies ist sehr performanceintensiv, vor allem, wenn Tabelle1 ODER Tabelle2 sehr viele Datensätze beinhaltet!!!

    Example - EXISTS:
    Code:
    select *
        from tabelle1 t1
        where EXISTS ( select 'x' from tabelle2 t2 where t1.Spalte1 = t2.Spalte1 )
    
    Diese liefert ALLE Datensätze von Tabelle1, wo die Spalte1 von Tabelle1 GLEICH der Spalte1 von Tabelle2 ist. (Tabelle1.Spalte1 = Tabelle2.Spalte1)
    (wie bei "Example - IN")

    Unterschied zu Example - IN:
    Hier wird die äußere Select - Anweisung ausgeführt und das SQL-Resultset im Cache des DBMS gespeichert. Anschließend wird das Subselect ausgeführt und ebenfalls im Cache gespeichert.
    Zuletzt werden beide SQL-Resultsets herangezogen und gejoined!!
    Daher kommen wir wieder auf das gleiche Ergebnis ( Tabelle1.Spalte1 = Tabelle2.Spalte1 )
    Somit ist die Performance deutlich besser als bei "IN"!!

    Ich hoffe, ich habe mich verständlich ausgedrückt und es ist nachvollziehbar!

    Lg
     
    Walter gefällt das.
  2. ukulele

    ukulele Datenbank-Guru

    Kann es sein das es dort Unterschiede im DBMS gibt? Ich habe mit SQL 2008 R2 Express und einer Tabelle mit 2,1 Mio Datensätzen die sich selbst vergleicht ( Jede Abfrage dauert 17 Sekunden) und in Kombination mit einer Tabelle mit 4.806 Datensätzen (Dauer 1 Sekunde) keinen Unterschied provozieren können. In allen Fällen, ob EXISTS oder IN habe ich die gleiche Abfragedauer mehrfach reproduzieren können.

    Entweder wird bei IN der Subselect genauso gecached wie bei EXISTS oder die 17 Sekunden sind eher netzwerkbedingt und die Unterscheide sind bei 2 Mio Datensätzen noch nicht messbar.
    Code:
    SELECT    *
    FROM    z_unt_bez_fragmente -- 17 Sekunden, 2.104.674
    SELECT    *
    FROM    z_unt_bez_fragmente
    WHERE    fk_untn IN (    SELECT    fk_untn
                            FROM    z_unt_bez_fragmente ) -- 17 Sekunden, 2.104.674
    SELECT    *
    FROM    z_unt_bez_fragmente t1
    WHERE    EXISTS (    SELECT    1
                        FROM    z_unt_bez_fragmente t2
                        WHERE    t1.fk_untn = t2.fk_untm ) -- 17 Sekunden, 2.104.674
    SELECT    *
    FROM    z_unt_bez_fragmente t1
    WHERE    EXISTS (    SELECT    1
                        FROM    ADRESSEN t2
                        WHERE    t2.SID_ADRESSEN = t1.fk_untm ) -- 17 Sekunden, 2.104.674
    SELECT    *
    FROM    z_unt_bez_fragmente
    WHERE    fk_untn IN (    SELECT    SID_ADRESSEN
                            FROM    ADRESSEN ) -- 17 Sekunden, 2.104.674
    SELECT    *
    FROM    ADRESSEN
    WHERE    SID_ADRESSEN IN (    SELECT    fk_untn
                                FROM    z_unt_bez_fragmente ) -- 1 Sekunde, 4.806
    SELECT    *
    FROM    ADRESSEN t1
    WHERE    EXISTS (    SELECT    1
                        FROM    z_unt_bez_fragmente t2
                        WHERE    t1.SID_ADRESSEN = t2.fk_untm ) -- 1 Sekunde, 4.806
     
    PLSQL_SQL und Walter gefällt das.
  3. PLSQL_SQL

    PLSQL_SQL Datenbank-Guru

    Das nenne ich echte Begeisterung!!!

    Toll gemacht ukulele!!!!

    Aber was ich noch nicht erwähnt habe, ist es doch so (bin mir gerade nicht ganz sicher), dass wenn im Subselect 2 Treffer zum äußeren Select gefunden werden, dass somit im äußeren Select 2 mal der gleiche Datensatz zurückgegeben wird. (1:n) Dies kann zwar mit DISTINCT verhindert werden, aber geht ziemlich sicher auf die Performance.

    D.h. aus diesem Grund sollte doch auch EXISTS besser sein.

    Keine Ahnung wie MSSQL 2008 R2 "IN" verarbeitet, vl. bilded dieser einen entsprechenden besseren Executionplan und behandelt das Subselect mit "IN" wie eine "EXISTS" !????

    Auf Netzwerkprobleme würde ich hier auf keinen Fall tippen! 2 Mio Datensätze sind schon etwas, kommt jedoch auch auf die Leistungsstärke des Datenbankservers an, ab wann solche Dinge spürbar werden!

    Lg
     
  4. ukulele

    ukulele Datenbank-Guru

    Ich habe bisher (auch in Fällen mit IN und DISTINCT) keine wirklichen Probleme gehabt, dennoch würde ich die EXISTS Lösung auch als eleganter ansehen. Bis vor geraumer Zeit wusste ich aber noch nichtmal, das ich im Subselect mit einem Alias auf Spalten aus dem Select gearbeitet werden kann :)

    Beim Testserver handelt es sich übrigens um ein produktives Windows 2003 R2 auf VMware mit nur einem Core (SQL Express nutzt eh nur einen Kern) der sonst nicht sehr viel zu tun hat. Allerdings läuft unsere ganze produktive Umgebung auf nur 2 Hosts was die Abfragedauer aber nicht beeinflusst. Daher hatte ich überlegt das eventuell die Netzwerkanbindung des Clients (nur 100 MBit), der die SELECT Daten empfängt der begrenzende Faktor sein könnte.

    PS: Die selbe Abfrage direkt auf dem Server dauert sogar 19 Sekunden. Ich denke mal ich will gar nicht wissen, warum^^
     
  5. PLSQL_SQL

    PLSQL_SQL Datenbank-Guru

    Cool!

    Danke nochmals für dein Feedback!
    Ich kann nur sagen, dass bei mir (Oracle 10g) immer ein deutlicher Unterschied zwischen "IN" und "EXISTS" besteht. Ich habe auch normale JOIN Abfragen mit EXISTS geteilt, um die JOINS somit in einem Stmt zu verringern und das Stmt zu beschleunigen. Dies ist jedoch nur möglich, wenn du in den letzteren Tabellen (welche du im EXISTS verwendest) KEINE Spalten (Attribute) zur Ausgabe benötigst!

    Lg
     
Die Seite wird geladen...

Diese Seite empfehlen

  1. Diese Seite verwendet Cookies. Wenn du dich weiterhin auf dieser Seite aufhältst, akzeptierst du unseren Einsatz von Cookies.
    Information ausblenden