Die Abfrage ist in SQL Server 2014 langsam und in SQL Server 2012 schnell

7

Bei der Migration einer unserer Datenbanken von SQL Server 2012 (SP1, CU2) auf SQL Server 2014 (SP1) sind einige seltsame Probleme aufgetreten.

Eine der Abfragen, die in SQL Server 2012 innerhalb von Sekunden abgeschlossen werden, scheint in SQL Server 2014 zu hängen.

SELECT  DISTINCT 
    src.[Id]
FROM
    [stg].[BaseVolumes] src
JOIN     
    [tmp].[Dates] d ON src.[CalWeek_Nmbr] = d.[CalYrWkDense_Nmbr]
WHERE   
    EXISTS (SELECT  *
            FROM    
                (SELECT     ctry.[ISOCode]                  AS  [Mkt_Code]
                            , so.[Code]                     AS  [SlsOrg_Code_AK]
                            , so.[DistributionChannelCode]  AS  [DistChnl_Code_AK]
                            , prd.[SupplierCode]                AS  [SKU_Code_AK]
                            , cl6.[Code]                        AS  [CstHierLvl06_Code_AK]
                            , lp.[BaseDateID]                   AS  [Dte_EK]
                 FROM   [PM_APP].[edw].[BaseVolumeDayCurrent]   lp
                 JOIN   [PM_APP].[dbo].[Country]                ctry    ON  lp.[CountryID] = ctry.[ID]
                 JOIN   [PM_APP].[dbo].[SalesOrganisation]      so      ON  lp.[SalesOrganisationID] = so.[ID]
                 JOIN   [PM_APP].[dbo].[Product]                prd     ON  lp.[ProductID] = prd.[ID]   
                 JOIN   [PM_APP].[dbo].[CustomerLevel6]         cl6     ON  lp.[CustomerID] = cl6.[ID]
                 WHERE  
                     lp.[ModifiedByApp] = 1) lkp
            WHERE   
                src.[Mkt_Code]                  =   lkp.[Mkt_Code]
                AND src.[SlsOrg_Code_AK]        =   lkp.[SlsOrg_Code_AK]
                AND src.[DistChnl_Code_AK]      =   lkp.[DistChnl_Code_AK]
                AND src.[SKU_Code_AK]           =   lkp.[SKU_Code_AK]
                AND src.[CstHierLvl06_Code_AK]  =   lkp.[CstHierLvl06_Code_AK]
                AND d.[Dte_EK]                  =   lkp.[Dte_EK]
        )

Reihenanzahl:

BaseVolumes:            23108 
Dates:                  18628 
BaseVolumeDayCurrent:   108115503 
Country:                249
SalesOrganisation:      29
Product:                18446
CustomerLevel6:         295

Wartestatistiken mit hohem CXPacket, aber es gibt eine hängende Aufgabe mit SOS_SCHEDULER_YIELD (Druck von sys.sysprocesses)

 spid | blocked | waittime | lastwaittype          | cpu     | physical_io 
 76   | 0       | 9886044  | CXPACKET              | 13902   | 31192
 76   | 0       | 0        | SOS_SCHEDULER_YIELD   | 9829719 | 83077
 76   | 0       | 11248    | CXPACKET              | 11110   | 0
.
.
.

Im Anhang finden Sie die Ausführungspläne von SQL Server 2012 und SQL Server 2014.

Jede Hilfe sehr geschätzt.

user2428710
quelle
Ist der maximale Speicher auf beiden Servern gleich? Können Sie auch versuchen, die Abfrage mit auszuführen OPTION (MAXDOP 1)? Sowie OPTION (QUERYTRACEON 4199, QUERYTRACEON 9481). Alternativ können Sie die Plananleitung als letzte Option verwenden.
Kin Shah

Antworten:

10

Die wahrscheinlichste Situation ist, dass der neue SQL 2014 Cardinality Estimator eine schlechte Zeilenschätzung für einen oder mehrere Joins in Ihrer Abfrage liefert. Dies hat SQL Server dazu veranlasst, einen ineffizienten Plan auszuwählen.

Wenn Sie die Abfrage in SQL 2014 mit aktiviertem "tatsächlichen Ausführungsplan einschließen" ausführen können, können Sie die folgende Abfrage auf einer anderen Registerkarte verwenden, um den Echtzeitfortschritt der Zeilen anzuzeigen, die durch die einzelnen Abfrageoperatoren fließen. Ich habe festgestellt, dass Sie nur einen geschätzten Plan für 2014 haben (im Vergleich zu einem tatsächlichen Plan für 2012), vermutlich weil Sie die Abfrage in SQL 2014 nicht vollständig ausführen können. Dadurch erhalten Sie möglicherweise mehr Einblick in die tatsächlichen Zeilen, die durch die Abfrage in fließen 2014 und führt Sie möglicherweise zu einer Möglichkeit, die Abfrage zu optimieren, die mit dem neuen Kardinalitätsschätzer effizient ausgeführt wird.

In der Zwischenzeit können Sie, bis Sie die Abfrage optimieren können, die Sie QUERYTRACEON mit dem Ablaufverfolgungsflag 9481 für diese Abfrage verwenden können, oder den Anweisungen von Brent Ozar folgen , die Datenbank auf der SQL 2012-Kompatibilitätsstufe auszuführen, und Ihre Abfragen sorgfältig mit dem neuen Kardinalitätsschätzer testen. und Aktualisieren der Kompatibilitätsstufe auf 120 (SQL 2014) erst, wenn Sie mit diesen Ergebnissen zufrieden sind.

/* Live query progress in SQL 2014 */
SELECT session_id,node_id,physical_operator_name, SUM(row_count) row_count, SUM(estimate_row_count) AS estimate_row_count, 
    CAST(SUM(row_count)*100 AS float)/NULLIF(SUM(estimate_row_count),0) AS percent_complete,
    SUM(elapsed_time_ms) AS elapsed_time_ms,
    SUM(cpu_time_ms) AS cpu_time_ms,
    SUM(logical_read_count) AS logical_read_count,
    SUM(physical_read_count) AS physical_read_count,
    SUM(write_page_count) AS spill_page_count,
    SUM(segment_read_count) AS segment_read_count,
    SUM(segment_skip_count) AS segment_skip_count,
    COUNT(*) AS num_threads
FROM sys.dm_exec_query_profiles 
WHERE session_id <> @@spid
GROUP BY session_id,node_id,physical_operator_name
ORDER BY session_id,node_id;
Geoff Patterson
quelle