none
Datenbankumstellung von Kompatibilität SQL-Server 2012 auf 2014 -> Performanceeinbruch bei bestimmter Aktion in der Anwendung RRS feed

  • Frage

  • Hi,

    wir setzen unter Anderem SQL-Server 2014 ein und haben hier eine Fachanwendung, die mit dem Kompatibilitätsmodus 2012 ganz normal läuft und sobald wir den Kompatibilitätsgrad auf 2014 setzen bricht die Performance beim Speichern des jeweiligen Vorgangs in der Anwendung dermaßen ein, dass das Speicher statt 1 Sekunde 10 Sekunden dauert.

    Wir haben das Problem durch Anwendungslog und Herumprobieren nun schon auf 4 Tabellen eingrenzen können. Sobald wir diese 4 Tabellen mit 

    UPDATE STATISTICS Tabellenname WITH FULLSCAN;

    aktualisieren, das Problem nicht mehr haben. Wir lassen Abends aber immer einen Task laufen, der den Befehl 

    exec sp_updatestats;

    für alle Datenbanken auf dem Server ausführt. Nachdem dieser gelaufen ist, ist das Problem wieder vorhanden. Kann mir das jemand erklären?

    Und sobald wir den Kompatibilitätsmodus wieder auf SQL-Server 2012 umstellen, läuft alles wieder wie geschmiert.

    Der Anwendungshersteller sagt auch, dass alle SQL-Server bis hin zu SQL-Server 2017 unterstützt werden.

    Eine weitere Kuriosität, die sich mir nicht ganz erschließt, dieses Verhalten tritt bei uns nur auf virtualisierten SQL-Servern auf. Wir haben Testweise einen SQL-Server 2014 auf einem Notebook mit Stromspar-Prozessor! und nur 4 GB RAM aufgesetzt und ein Backup der Datenbank dort eingespielt und versucht, den Fehler dort nachzustellen, aber dort läuft es einwandfrei.

    Donnerstag, 18. Juli 2019 14:08

Antworten

  • Hallo Jan,

    es ist eindeutig der neue CE, der Dir hier Probleme bereitet. Das fängt bereits beim ersten Operator (INDEX SEEK) an. Während der CE 70 (<= 2012) nur von 1 Datensatz ausgeht, vermutet der neue CE (>= 2014) bereits 6 Datensätze.

    Den größten Impact hast Du beim MERGE-Command, da mit dem neuen CE geschätzte 35 Mio Datensätze gelesen werden müssen.

    Beim UPDATE vermutet der QE mit CE 70 ca. 5 Mio Datensätze, während der neue CE 2,2 Mio Datensätze meint, updaten zu müssen.

    AUsserdem - so vermute ich - ist die Abfrage mit CE 70 auch deswegen schneller, da sie parallelisiert während die Abfrage mit CE 120 single threaded ausgeführt wird.

    Wenn Du sicher stellen möchtest, dass die Abfrage immer mit CE 70 ausgeführt wird, erweitere die Abfrage wie folgt:

    UPDATE ERGWERT  SET GELOESCHT = 'J'  WHERE ERGWERT.ERGZEITSCHIENE_ID IN               
         ( SELECT ERGZEITSCHIENE.ERGZEITSCHIENE_ID                       
             FROM ERGZEITSCHIENE, ERGHHPERSON, ERGMATRIX                 
            WHERE ERGZEITSCHIENE.ERGHHPERSON_ID = ERGHHPERSON.ERGHHPERSON_ID  
              AND ERGHHPERSON.ERGMATRIX_ID = ERGMATRIX.ERGMATRIX_ID      
              AND ERGMATRIX.FALL_ID = '100000000018336' AND ERGMATRIX.AB = '2019-07-01 00:00:00.000')
    OPTION	(QUERYTRACEON 9481)
    -- TF 9481 zwingt die Abfrage, den alten CE zu verwenden
    -- https://sqlserverscotsman.wordpress.com/2016/11/28/a-guide-on-forcing-the-legacy-ce/
    
    

    Wenn Du mehr darüber wissen möchtest, wie der SQL Server auf seine geschätzten Datenmengen kommt, hilft (Vorsicht, schwere Kost!) ein Beitrag von Dmitri Pilugin eventuell weiter:

    https://www.sqlshack.com/cardinality-estimation-process/


    Uwe Ricken (Blog | Twitter)
    Microsoft Certiied Master - SQL Server 2008
    Microsoft Certified Solution Master - CHARTER Data Platform
    Microsoft Certified Solution Expert - Data Platform
    db Berater GmbH
    Microsoft SQL Server Blog (german only)

    • Als Antwort markiert Jan Merker Montag, 22. Juli 2019 13:32
    Montag, 22. Juli 2019 11:37

Alle Antworten

  • Hi,

    welche Version genau setzt ihr ein?

    SELECT @@Version

    Aber so ganz allgemein würde ich mir mal die Abfragepläne anschauen (evtl. mal mit dem kostenlosen SentryOne Plan Explorer). Dort wird es ggfs. erhebliche Unterschiede geben. Meist kann man daran dann schon erkennen, wo es hakt.

     


    Gruß, Stefan
    Microsoft MVP - Visual Developer ASP/ASP.NET (2001-2018)
    https://www.asp-solutions.de/ - IT Beratung, Softwareentwicklung, Remotesupport


    Donnerstag, 18. Juli 2019 15:08
    Moderator
  • Microsoft SQL Server 2014 (SP3-CU3) (KB4491539) - 12.0.6259.0 (X64) Apr 1 2019 22:19:54 Copyright (c) Microsoft Corporation Enterprise Edition: Core-based Licensing (64-bit) on Windows NT 6.3 <X64> (Build 14393: ) (Hypervisor)
    Donnerstag, 18. Juli 2019 15:25
  • Guten Abend,

    für sp_updatestats gibt es eine Option 'resample'

    exec sp_updatestats 'resample'

    Mehr Informationen hierzu unter: https://docs.microsoft.com/de-de/sql/relational-databases/system-stored-procedures/sp-updatestats-transact-sql?view=sql-server-2017

    Von einem (auch möglichen) FULLSCAN für alle Tabellen aller Datenbanken wird überwiegend abgeraten.

    Von führenden Unternehmen wird dies verwendet:

    https://ola.hallengren.com/sql-server-index-and-statistics-maintenance.html

    wobei eigentlich die Datenbankoptionen "Statistiken automatisch erstellen" = TRUE und "Statistiken automatisch aktualisieren" = TRUE überwiegend ausreichen sollten.

    Schönen Abend.



    • Bearbeitet Joerg_x Donnerstag, 18. Juli 2019 17:45
    Donnerstag, 18. Juli 2019 17:43
  • Danke für die Infos.

    Allerdings verstehe ich nicht ganz, wieso es nach einem FULLSCAN optimal läuft und wenn ich direkt danach den normalen sp_updatestats ausführe wieder langsam ist.

    Für mein Verständniss dürfte der sp_updatestats doch nach einem FULLSCAN gar nichts zum optimieren finden und daher auch nichts ändern, oder macht sp_updatestats noch etwas anderes? 

    Freitag, 19. Juli 2019 06:27
  • Speichern heißt ein simples INSERT oder gibt es drum rum auch noch Abfragen? Wenn dann sieh diese Thread: SQL Server Umzug von 2012 zu 2017 - Daily Import dauert extrem lange

    Olaf Helper

    [ Blog] [ Xing] [ MVP]

    Freitag, 19. Juli 2019 06:39
  • Beim Speichern werden diverse Dinge ausgeführt. Wir haben eine Logdatei, in der wir erkennen können, dass bei einem Update die Verzögerungen auftreten (wie bereits geschrieben nur im Kompatibilitätslevel SQL 2014, in 2012 ist alles gut):

    (Die Fragezeichen sind hier als Platzhalter zu verstehen)

    UPDATE ERGWERT  SET GELOESCHT = 'J'  WHERE ERGWERT.ERGZEITSCHIENE_ID IN               
         ( SELECT ERGZEITSCHIENE.ERGZEITSCHIENE_ID                       
             FROM ERGZEITSCHIENE, ERGHHPERSON, ERGMATRIX                 
            WHERE ERGZEITSCHIENE.ERGHHPERSON_ID = ERGHHPERSON.ERGHHPERSON_ID  
              AND ERGHHPERSON.ERGMATRIX_ID = ERGMATRIX.ERGMATRIX_ID      
              AND ERGMATRIX.FALL_ID = ? AND ERGMATRIX.AB = ?)

    Freitag, 19. Juli 2019 07:17
  • Dann würde ich mal den Ausführungsplan zwischen 2012 und 2014 vergleichen um zu sehen, was anders ist.

    Olaf Helper

    [ Blog] [ Xing] [ MVP]

    Freitag, 19. Juli 2019 08:09
  • Ok, da muss ich mich mal einlesen, wie ich dies mache. Bisher habe ich soetwas noch nicht gemacht.

    Was mich aber immer noch stutzig macht ist die Tatsache, dass die Abfrage nach einem 

    UPDATE STATISTICS Tabellenname WITH FULLSCAN;

    die Abfrage funktioniert, und sobald ich die Statistiken irgendwie anders aktualisiere (sei es sp_updatestats oder das Script von Hallengren) wieder grottenlahm läuft. Das verstehe ich einfach nicht.

    Freitag, 19. Juli 2019 09:39
  • Dann schau dir auch hier die Ausführungspläne vor und nach der Ausführung des jeweiligen Befehls an.

    Ich hatte dir ja oben ein Tool verlinkt, mit dem man doch eine erheblich besser Übersicht über die Ausführungspläne erhälten kann. Das sollte dir helfen. Falls nicht, poste mal die Ausführungspläne hier.


    Gruß, Stefan
    Microsoft MVP - Visual Developer ASP/ASP.NET (2001-2018)
    https://www.asp-solutions.de/ - IT Beratung, Softwareentwicklung, Remotesupport

    Freitag, 19. Juli 2019 10:38
    Moderator
  • Siehe Anzeigen eines tatsächlichen Ausführungsplans

    Du kannst die Pläne auch Online bereit stellen, dann schauen wir es uns an: https://www.brentozar.com/pastetheplan/


    Olaf Helper

    [ Blog] [ Xing] [ MVP]


    Freitag, 19. Juli 2019 12:58
  • Hallo Maverik,

    "Allerdings verstehe ich nicht ganz, wieso es nach einem FULLSCAN optimal läuft und wenn ich direkt danach den normalen sp_updatestats ausführe wieder langsam ist."

    Das kann sehr wohl passieren, da Microsoft SQL Server bei sp_updatestats nur einen Prozentanteil der Datenmenge nimmt, um die Statistiken zu aktualisieren. Das kann man am folgenden Beispiel sehr schön erkennen:

    USE demo_db;
    GO
    
    SELECT *
    INTO dbo.messages
    FROM sys.messages;
    GO
    
    CREATE NONCLUSTERED INDEX x1 ON dbo.messages (severity);
    GO
    
    -- check the statistics
    DBCC SHOW_STATISTICS(N'dbo.messages', N'x1');
    GO
    

    Zunächst wird eine Tabelle mit einem Index auf [severity] erstellt. Bei der Erstellung des Indexes werden die Statistiken mit 100% aller Daten erstellt.

    Wenn nun eine Abfrage auf [severity] = 12 ausgeführt wird, "schätzt" SQL Server, dass 22 Datensätze zurückgeliefert werden. Werden nun - wie von Dir beschrieben - die Statistiken mit sp_updatestats aktualisiert, ergibt sich für das Histogramm ein vollkommen anderes Bild:


    Uwe Ricken (Blog | Twitter)
    Microsoft Certiied Master - SQL Server 2008
    Microsoft Certified Solution Master - CHARTER Data Platform
    Microsoft Certified Solution Expert - Data Platform
    db Berater GmbH
    Microsoft SQL Server Blog (german only)

    Montag, 22. Juli 2019 06:57
  • Ok, das leuchtet mir ein. Allerdings:

    "Eine weitere Kuriosität, die sich mir nicht ganz erschließt, dieses Verhalten tritt bei uns nur auf virtualisierten SQL-Servern auf. Wir haben Testweise einen SQL-Server 2014 auf einem Notebook mit Stromspar-Prozessor! und nur 4 GB RAM aufgesetzt und ein Backup der Datenbank dort eingespielt und versucht, den Fehler dort nachzustellen, aber dort läuft es einwandfrei."

    Wieso passiert dies nur auf virtualisierten SQL-Servern? Wir haben auf einem Notebook testweise einen 2014er SQL-Server mit gleichem Patchlevel installiert und die Datenbank dort laufen lassen. Dort haben wir dieses Phänomen nicht. Gibt es zwischen physikalischen und virtuellen SQL-Server auch einen Unterschied?

    Montag, 22. Juli 2019 09:28
  • Hallo Maverick,

    grundsätzlich sollte es KEINEN Unterschied machen, ob virtuell oder physikalisch. Den Unterschied macht die Hardware. Microsoft SQL Server muss für die Erstellung eines geeigneten Plans die Hardwareumgebung mit berücksichtigen.

    Hat z. B. Deine virtuelle Maschine 8 Cores während Dein Laptop lediglich 4 Cores besitzt, ändert sich der Sachverhalt (z. B. im Rahmen von Parallelisierung, etc).

    Gleiches gilt natürlich auch für die Geschwindigkeit der Prozessoren. Wenn Du ein Architekt wärst, würdest Du eventuell mit einem Mitarbeiter, der schneller arbeiten kann, 4 weitere Mitarbeiter einsparen wollen, weil Du Ressourcen schonen möchtest, oder :)

    Insgesamt berücksichtigt SQL Server sowohl RAM als auch CPU in der Quantität wie auch in der Qualität.

    Wenn Du also einen Vergleich erzielen möchtest, solltest Du zunächst auf gleiche Rahmenbedingungen bezüglich der oben genannten Kriterien achten.

    Interessant wäre es, wenn Du hier mal BEIDE Ausführungspläne posten könntest. Dann kann man sich die Unterschiede etwas genauer anschauen. Du kannst das auch über ein ONLINE Portal von Brent Ozar machen und den Link hier posten.

    https://www.brentozar.com/pastetheplan/


    Uwe Ricken (Blog | Twitter)
    Microsoft Certiied Master - SQL Server 2008
    Microsoft Certified Solution Master - CHARTER Data Platform
    Microsoft Certified Solution Expert - Data Platform
    db Berater GmbH
    Microsoft SQL Server Blog (german only)

    Montag, 22. Juli 2019 09:35
  • Das hier ist der Ausführungsplan unter Kompatibilität 2012

    Kompatibilität 2012

    und hier mit dem Kompatibilitätsmodus 2014

    Kompatibilität 2014

    oder braucht ihr die XML-Ausgabe?

    Montag, 22. Juli 2019 09:57
  • Ich kann leider nichts sehen. XML wäre besser.

    Kannst Du die XML-Files auf ONEDRIVE o. ä. ablegen?
    Dann kann man sich die herunterladen.


    Uwe Ricken (Blog | Twitter)
    Microsoft Certiied Master - SQL Server 2008
    Microsoft Certified Solution Master - CHARTER Data Platform
    Microsoft Certified Solution Expert - Data Platform
    db Berater GmbH
    Microsoft SQL Server Blog (german only)

    Montag, 22. Juli 2019 09:59
  • Kompatibilität 2012

    Kompatibilität 2014

    Unter 2014 dauert die Abfrage 10 Sekunden unter 2012 wird sie sofort ausgeführt.

    Montag, 22. Juli 2019 10:12
  • Hallo Jan,

    es ist eindeutig der neue CE, der Dir hier Probleme bereitet. Das fängt bereits beim ersten Operator (INDEX SEEK) an. Während der CE 70 (<= 2012) nur von 1 Datensatz ausgeht, vermutet der neue CE (>= 2014) bereits 6 Datensätze.

    Den größten Impact hast Du beim MERGE-Command, da mit dem neuen CE geschätzte 35 Mio Datensätze gelesen werden müssen.

    Beim UPDATE vermutet der QE mit CE 70 ca. 5 Mio Datensätze, während der neue CE 2,2 Mio Datensätze meint, updaten zu müssen.

    AUsserdem - so vermute ich - ist die Abfrage mit CE 70 auch deswegen schneller, da sie parallelisiert während die Abfrage mit CE 120 single threaded ausgeführt wird.

    Wenn Du sicher stellen möchtest, dass die Abfrage immer mit CE 70 ausgeführt wird, erweitere die Abfrage wie folgt:

    UPDATE ERGWERT  SET GELOESCHT = 'J'  WHERE ERGWERT.ERGZEITSCHIENE_ID IN               
         ( SELECT ERGZEITSCHIENE.ERGZEITSCHIENE_ID                       
             FROM ERGZEITSCHIENE, ERGHHPERSON, ERGMATRIX                 
            WHERE ERGZEITSCHIENE.ERGHHPERSON_ID = ERGHHPERSON.ERGHHPERSON_ID  
              AND ERGHHPERSON.ERGMATRIX_ID = ERGMATRIX.ERGMATRIX_ID      
              AND ERGMATRIX.FALL_ID = '100000000018336' AND ERGMATRIX.AB = '2019-07-01 00:00:00.000')
    OPTION	(QUERYTRACEON 9481)
    -- TF 9481 zwingt die Abfrage, den alten CE zu verwenden
    -- https://sqlserverscotsman.wordpress.com/2016/11/28/a-guide-on-forcing-the-legacy-ce/
    
    

    Wenn Du mehr darüber wissen möchtest, wie der SQL Server auf seine geschätzten Datenmengen kommt, hilft (Vorsicht, schwere Kost!) ein Beitrag von Dmitri Pilugin eventuell weiter:

    https://www.sqlshack.com/cardinality-estimation-process/


    Uwe Ricken (Blog | Twitter)
    Microsoft Certiied Master - SQL Server 2008
    Microsoft Certified Solution Master - CHARTER Data Platform
    Microsoft Certified Solution Expert - Data Platform
    db Berater GmbH
    Microsoft SQL Server Blog (german only)

    • Als Antwort markiert Jan Merker Montag, 22. Juli 2019 13:32
    Montag, 22. Juli 2019 11:37
  • Vielen Dank für die schnelle Hilfe!

    Wir haben das Traceflag jetzt auf dem Testserver gesetzt und es funktioniert. 

    Montag, 22. Juli 2019 13:32
  • Hallo Jan,

    auch wenn Du die Antwort von Uwe bereits als Lösung Deines Problems markiert hast.

    Interessehalber:

    Das ist Deine Originalabfrage, nur mit einem SELECT (die Antwortzeiten MSSQL 2012 und MSSQL 2014 sollten identisch sein):

    SELECT ERGWERT.geloescht
    FROM ERGWERT
    WHERE ERGWERT.ERGZEITSCHIENE_ID IN               
          (SELECT ERGZEITSCHIENE.ERGZEITSCHIENE_ID                       
           FROM ERGZEITSCHIENE, ERGHHPERSON, ERGMATRIX                 
           WHERE ERGZEITSCHIENE.ERGHHPERSON_ID = ERGHHPERSON.ERGHHPERSON_ID  
            AND ERGHHPERSON.ERGMATRIX_ID = ERGMATRIX.ERGMATRIX_ID      
            AND ERGMATRIX.FALL_ID = '100000000018336' AND ERGMATRIX.AB = '2019-07-01 00:00:00.000')

    Ich finde es ungünstig, Beziehungen zwischen Tabellen in der Bedingung (WHERE Klausel) abzubilden, also zunächst ein kartesisches Produkt zu bilden, um dann die Datenmenge wieder zu filtern. Übersichtlich ist dies auch nicht, weil man damit "echte" Filter von Beziehungen zwischen Tabellen nur sehr schwer auseinander halten kann.

    Bereinigt würde das dann so aussehen (ändern sich damit schon die Antwortzeiten und Ausführungspläne)?

    SELECT ew.geloescht
    FROM ERGWERT ew    
    WHERE ERGWERT.ERGZEITSCHIENE_ID IN               
          (SELECT es.ERGZEITSCHIENE_ID                       
           FROM ERGZEITSCHIENE es
            LEFT JOIN ERGHHPERSON ep    ON (es.ERGHHPERSON_ID = ep.ERGHHPERSON_ID)
            LEFT JOIN ERGMATRIX em      ON (ERGHHPERSON.ERGMATRIX_ID = ERGMATRIX.ERGMATRIX_ID)             
           WHERE em.FALL_ID = '100000000018336' 
                AND em.AB = '2019-07-01 00:00:00.000')

    Den SUBSELECT (WHERE IN) würde ich auch auslagern, weil dies nach meinen Erfahrungen zu deutlichen Performancegewinnen führt, entweder in eine CTE oder in eine temporäre Tabelle, auf die man Indexe setzen kann (ändern sich damit  die Antwortzeiten und Ausführungspläne?)

    WITH Vorberechnung AS
    (
        SELECT es.ERGZEITSCHIENE_ID                       
               FROM ERGZEITSCHIENE es
                LEFT JOIN ERGHHPERSON ep    ON (es.ERGHHPERSON_ID = ep.ERGHHPERSON_ID)
                LEFT JOIN ERGMATRIX em      ON (ERGHHPERSON.ERGMATRIX_ID = ERGMATRIX.ERGMATRIX_ID)             
               WHERE em.FALL_ID = '100000000018336' 
                    AND em.AB = '2019-07-01 00:00:00.000')
    )
    
    SELECT ew.geloescht
    FROM ERGWERT ew    
    WHERE ERGWERT.ERGZEITSCHIENE_ID IN               
          (SELECT v.ERGZEITSCHIENE_ID                       
           FROM Vorberechnung v)

    Ich denke, dass es nicht der MSSQL 2014 mit seinem Kompabilitätsgrad ist, der hier Probleme macht, sondern die Abfrage selbst, die nicht optimal ist.

    Schönen Abend.



    • Bearbeitet Joerg_x Montag, 22. Juli 2019 19:04
    Montag, 22. Juli 2019 19:02
  • Ich finde es ungünstig, Beziehungen zwischen Tabellen in der Bedingung (WHERE Klausel) abzubilden, also zunächst ein kartesisches Produkt zu bilden

    Jörg, das nennt sich Old-Style JOIN und bildet in keiner Weise ein kartesisches Produkt.


    Olaf Helper

    [ Blog] [ Xing] [ MVP]

    Dienstag, 23. Juli 2019 05:59
  • Olaf,

    überzeugt hast Du mich noch nicht.

    Die Abfrage, so wie sie geschrieben wurde, ist die Ursache für das Verhalten. Hier ist es ganz gut erläutert:

    https://www.mssqltips.com/sqlservertutorial/3201/how-join-order-can-affect-the-query-plan/

    und erklärt meiner Meinung nach auch die großen Unterschiede, die Uwe oben beschrieben hat:

    "Den größten Impact hast Du beim MERGE-Command, da mit dem neuen CE geschätzte 35 Mio Datensätze gelesen werden müssen."

    Schöne Grüße.

    Donnerstag, 25. Juli 2019 16:00
  • Guten Morgen Jörg,

    Olaf hat schon Recht - der QE bekommt das allein hin (smart guy :)). Das auf MSSQLTips gezeigte Beispiel ist unpassend, da der Autor einen TABLEHINT verwendet. Sobald Du Tablehints verwendest, ist die QE "beleidigt" und meint, dass Du smarter bist als sie. In diesem Fall werden die JOINS in der Reihenfolge abgearbeitet, wie sie im Code verwendet werden.

    SELECT	COUNT_BIG(*)
    FROM	dbo.CustomerOrders AS CO
    		INNER JOIN dbo.Customers AS C
    		ON (CO.Customer_Id = C.Id)
    GO

    Die Abfrage verwendet den ANSI 99 Standard und man kann sehr gut erkennen, dass SQL Server zunächst die Tabelle dbo.Customers verwendet (obwohl ich im Code CustomerOrders zuerst angegeben habe). Das nächste Beispiel verwendet die gleiche Abfrage; nur diesmal verwende ich einen TABLEHINT.

    SELECT	COUNT_BIG(*)
    FROM	dbo.CustomerOrders AS CO
    		INNER JOIN dbo.Customers AS C
    		ON (CO.Customer_Id = C.Id)
    OPTION	(MERGE JOIN)
    GO

    Wie Du sehr gut erkennen kannst, hält sich SQL Server nun an die Reihenfolge der Tabellen, wie sie in der Abfrage aufgeführt werden. Das nächste Beispiel zeigt einen "old style JOIN"

    SELECT	COUNT_BIG(*)
    FROM	dbo.CustomerOrders AS CO,
    		dbo.Customers AS C
    WHERE	CO.Customer_Id = C.Id;
    GO

    Wie Du erkennen kannst, ist der Plan identisch mit Plan 1.

    Grüße aus dem heißen Hamburg...


    Uwe Ricken (Blog | Twitter)
    Microsoft Certiied Master - SQL Server 2008
    Microsoft Certified Solution Master - CHARTER Data Platform
    Microsoft Certified Solution Expert - Data Platform
    db Berater GmbH
    Microsoft SQL Server Blog (german only)

    Freitag, 26. Juli 2019 05:47
  • Hallo Uwe,

    vielen Dank für Deine Erläuterungen.

    Allerdings findet sich hier ein gleichlautender Hinweis (ebenfalls von MVP's):

    https://social.technet.microsoft.com/wiki/contents/articles/25668.transact-sql-join-order.aspx

    Unter:

    Conclusions and General Rule of Thumb findest Du:

    "By default, JOINs are done in left to right order.
    Tables with less amount of rows pushed to the beginning of the process.
    We can try to change the order of JOINs in the query."

    Schöne Grüße zurück aus dem nun wieder etwas kühleren NRW.

    Montag, 29. Juli 2019 16:47
  • Hallo Jörg,

    vielen Dank für den Link zum Artikel von Ronen. Im Kern bestätigt er meine Ausführungen beweist aber - ebenfalls durch Query Hints - die zweite Aussage :)

    Der Query Optimizer arbeitet "cost based" und wenn z. B. ein NESTED LOOP effizienter ist für eine "große" Tabelle, dann kann es sehr wohl sein, dass auch die größere Tabelle zuerst verwendet wird.

    Wenn z. B. (basierend auf den Beispielen von Ronen) ein Prädikat auf T3 verwendet wird, das nur ein paar Daten zurückliefert, würde T3 in einer Beziehung zwischen T1 und T3 (JOIN) immer zuerst genommen werden.

    Neben den IO-Kosten spielen für den QE auch die Kosten für die Operationen eine wichtige Rolle. Aus diesem Grund kann von Aussage 1 aus dem von Dir zitierten Artikel durch den QE abgewichen werden.

    Liebe Grüße aus Heilbronn...


    Uwe Ricken (Blog | Twitter)
    Microsoft Certiied Master - SQL Server 2008
    Microsoft Certified Solution Master - CHARTER Data Platform
    Microsoft Certified Solution Expert - Data Platform
    db Berater GmbH
    Microsoft SQL Server Blog (german only)

    Dienstag, 30. Juli 2019 08:36