SQL Server 2012(SP1、CU2)からSQL Server 2014(SP1)へのデータベースの移行中に、いくつかの奇妙な問題が発生しました。
SQL Server 2012で数秒以内に完了するクエリの1つがSQL Server 2014でハングしているようです。
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]
)
行数:
BaseVolumes: 23108
Dates: 18628
BaseVolumeDayCurrent: 108115503
Country: 249
SalesOrganisation: 29
Product: 18446
CustomerLevel6: 295
高いCXPacketを示す統計を待機しますが、SOS_SCHEDULER_YIELDで1つのハングしているタスクがあります(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
.
.
.
添付されているのは、SQL Server 2012およびSQL Server 2014の実行計画です。
どんな助けも大歓迎です。
最も可能性の高い状況は、 新しいSQL 2014 Cardinality Estimator がクエリ内の1つ以上の結合の行推定値を低下させ、SQL Serverが非効率的な計画を選択するようになったことです。
「実際の実行計画を含める」をオンにしてSQL 2014でクエリを実行できる場合は、以下のクエリを別のタブで使用して、各クエリ演算子を通過する行のリアルタイムの進行状況を表示できます。おそらくSQL 2014でクエリを完全に実行できないため、2014年の推定計画(2012年の実際の計画と比較して)しかないことに気付きました。これにより、クエリを通過する実際の行をより詳細に把握できます。新しいCardinality Estimatorを使用して効率的に実行されるクエリを微調整する方法につながる可能性があります。
それまでの間、クエリを最適化できるようになるまで、このクエリに対してQUERYTRACEON
トレースフラグ9481付き を使用するか、または Brent Ozarのアドバイス of SQL 2012互換性レベルでデータベースを実行し、新しいCardinality Estimatorを使用してクエリを慎重にテストし、これらの結果に満足したら、互換性レベルを120(SQL 2014)にのみ更新します。
/* 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;