T-SQL では、複数のクエリを一つのバッチとして実行できる為、無理してサブクエリ化したような
クエリは、ステップ分けした方が大幅に性能向上できる場合がある
(例: Exadata40分 / Synapse SQL 当初 60分超 ⇒ 3.5分)
T-SQL のメリットを最大化する
29
--------------------------------------------------------------------------
-- Query-1 の結果が1件 ★インメモリ
--------------------------------------------------------------------------
--// 個別変数
DECLARE @DeviceId NCHAR(10)
DECLARE @Temperature INT
--// Query-1
SELECT TOP 1 @DeviceId = DeviceId, @Temperature = Temperature
FROM dbo.asalog ORDER BY Temperature DESC;
--// Query-2
SELECT a.*, @Temperature Temperature FROM dbo.asalog a
WHERE a.DeviceId = @DeviceId;
--------------------------------------------------------------------------
-- Query-1 の結果が小規模 (~数万件) ★インメモリ
--------------------------------------------------------------------------
--// テーブル変数
DECLARE @tableVal TABLE
(
DeviceId NCHAR(10),
Temperature INT
)
--// Query-1
INSERT INTO @tableVal
SELECT TOP 1000 * FROM dbo.asalog ORDER BY Temperature DESC;
--// Query-2
SELECT a.*, t.Temperature FROM dbo.asalog a
INNER JOIN @tableVal t ON a.DeviceId = t.DeviceId;
--------------------------------------------------------------------------
-- Query-1 の結果が中規模 (~数十万件) ★インメモリ
-- CTE (Common Table Expression) の利用
--------------------------------------------------------------------------
--// CTE (Common Table Expression)
WITH table_cte (DeviceId, Temperature)
AS
(
--// Query-1
SELECT TOP 100000 * FROM dbo.asalog ORDER BY Temperature DESC
)
--// Query-2
SELECT a.*, t.Temperature FROM dbo.asalog a
INNER JOIN table_cte t ON a.DeviceId = t.DeviceId;
--------------------------------------------------------------------------
-- Query-1 の結果が大規模 (数百万件以上) ★一時テーブル on tempDB
-- SQLDB BC/Hyperscale, Synapse SQL の場合、tempDB は NVMe SSD 上なので高速
--------------------------------------------------------------------------
--// 一時テーブル削除
IF OBJECT_ID(N'tempdb..#table1',N'U') IS NOT NULL
DROP TABLE #table1;
--// Query-1 to 一時テーブル
SELECT TOP 2000000 * INTO #table1 FROM dbo.asalog ORDER BY Temperature DESC;
--// Query-2
SELECT a.*, t.Temperature FROM dbo.asalog a
INNER JOIN #table1 t ON a.DeviceId = t.DeviceId;
チェック対象:1 分集計とした以下のメトリクスをチェックし、定常的に負荷が高い場合、DWU 追加を検討
•CPU used percentage 最大値
• Memory used percentage 最大値
• Local tempDB used percentage 最大値 (ソート, データ移動, Polybase によるロード, 一時テーブルで利用)
• Adaptive cache hit percentage 平均値 (クエリ実行時に列ストアデータが NVMe SSD に載っている割合) ⇒ 80% 以上が目安
• Workload group active queries 合計
• Workload group queued queries 合計 ⇒ 定常的にキュー待ちが大量に起きていないか
キャパシティが足りているかどうかをチェック
32
33.
チェック対象:以下クエリ実行時の [COMPRESSED_rowgroup_rows_XXX] 列の値は、104万行に近いほど品質が良い
問題の原因:データロード時のリソースクラス or ワークロード グループの REQUEST_MIN_RESOURCE_GRANT_PERCENT の値が小さ過ぎる
列ストア セグメントの品質を疑う
33
※参照:https://docs.microsoft.com/ja-jp/azure/synapse-analytics/sql-data-warehouse/sql-data-warehouse-tables-index#optimizing-clustered-columnstore-indexes
----------------------------------------------------------------------------------
-- CCI セグメント品質のチェック (簡易版)
----------------------------------------------------------------------------------
-- [table_partition_count] パーティション数
-- [row_count_total] トータル行数
-- [COMPRESSED_rowgroup_rows] 圧縮済み行グループのトータル行数
-- [COMPRESSED_rowgroup_rows_MIN] 圧縮済み行グループ内の最小行数
-- [COMPRESSED_rowgroup_rows_MAX] 圧縮済み行グループ内の最大行数
-- [COMPRESSED_rowgroup_rows_AVG] 圧縮済み行グループ内の平均行数
-- [COMPRESSED_rowgroup_rows_DELETED] 行グループ内の論理削除された行数
----------------------------------------------------------------------------------
SELECT
s.name AS [schema_name]
, t.name AS [table_name]
, COUNT(DISTINCT rg.[partition_number]) AS [table_partition_count]
, SUM(rg.[total_rows]) AS [row_count_total]
, SUM(CASE WHEN rg.[State] = 3 THEN rg.[total_rows] ELSE 0 END) AS [COMPRESSED_rowgroup_rows]
, AVG(CASE WHEN rg.[State] = 3 THEN rg.[total_rows] ELSE NULL END) AS [COMPRESSED_rowgroup_rows_AVG]
, MIN(CASE WHEN rg.[State] = 3 THEN rg.[total_rows] ELSE NULL END) AS [COMPRESSED_rowgroup_rows_MIN]
, MAX(CASE WHEN rg.[State] = 3 THEN rg.[total_rows] ELSE NULL END) AS [COMPRESSED_rowgroup_rows_MAX]
, SUM(CASE WHEN rg.[State] = 3 THEN rg.[deleted_rows] ELSE 0 END) AS [COMPRESSED_rowgroup_rows_DELETED]
, SUM(CASE WHEN rg.[State] = 1 THEN rg.[total_rows] ELSE 0 END) AS [OPEN_rowgroup_rows]
, AVG(CASE WHEN rg.[State] = 1 THEN rg.[total_rows] ELSE NULL END) AS [OPEN_rowgroup_rows_AVG]
, MIN(CASE WHEN rg.[State] = 1 THEN rg.[total_rows] ELSE NULL END) AS [OPEN_rowgroup_rows_MIN]
, MAX(CASE WHEN rg.[State] = 1 THEN rg.[total_rows] ELSE NULL END) AS [OPEN_rowgroup_rows_MAX]
, 'ALTER INDEX ALL ON ' + s.name + '.' + t.NAME + ' REBUILD;' AS [Rebuild_Index_SQL]
FROM sys.[pdw_nodes_column_store_row_groups] rg
JOIN sys.[pdw_nodes_tables] nt ON rg.[object_id] = nt.[object_id]
AND rg.[pdw_node_id] = nt.[pdw_node_id]
AND rg.[distribution_id] = nt.[distribution_id]
JOIN sys.[pdw_table_mappings] mp ON nt.[name] = mp.[physical_name]
JOIN sys.[tables] t ON mp.[object_id] = t.[object_id]
JOIN sys.[schemas] s ON t.[schema_id] = s.[schema_id]
--WHERE s.name = @schemaName AND t.name = @tableName
GROUP BY s.[name], t.[name]
ORDER BY s.[name], t.[name]
34.
チェック対象:以下クエリ実行時の [distribution_id] 列毎の[row_count] 列の値を見て、片寄りが無いかを確認
問題の原因:分散キーに設定した列が適切で無い (=カージナリティが低い or 値に片寄りがある) 可能性が高い
ディストリビューションのデータの偏りを疑う
34
※参照:https://docs.microsoft.com/ja-jp/azure/synapse-analytics/sql-data-warehouse/sql-data-warehouse-tables-distribute#determine-if-the-table-has-data-skew
★dbo.vTableSizes ビューは、参照先のリンクに定義がある
----------------------------------------------------------------------------------
-- 特定のノード/ディストリビューションにデータの偏りがないかのチェック
----------------------------------------------------------------------------------
-- 特定のテーブルについてノードにデータの片寄りが無いか
DBCC PDW_SHOWSPACEUSED('schema_name.table_name');
-- ディストリビューションの 10% 以上の偏りを抽出
select
two_part_name
, pdw_node_id
, pdw_node_type
, distribution_id
, dist_name,partition_nmbr
, row_count
, distribution_column
, distribution_policy_name
, index_type_desc
from dbo.vTableSizes -- ★★ このビューは、参照先のリンクにスクリプトがある
where two_part_name in
(
select two_part_name
from dbo.vTableSizes
where row_count > 0
group by two_part_name
having (max(row_count * 1.000) - min(row_count * 1.000))/max(row_count * 1.000) >= .10
)
order by two_part_name, distribution_id, row_count
;
35.
チェック対象:以下クエリ実行時の [operation_type] 列毎の[total_elapsed_time], [row_count] の値を見て、時間・件数が大きくないか確認
問題の原因:
• BroadcastMoveOperation (全データを全ノードへ移動) :レプリケート テーブル適用について検討が必要
• ShuffleMoveOperation (ジョインに必要なデータの移動):ノード内でジョインが完結していない ⇒ 結合キー (列) を分散キーに出来ないか検討が必要
コンピュート ノード間でデータ移動が大量に発生していないか疑う
35
※参照:https://docs.microsoft.com/ja-jp/sql/relational-databases/system-dynamic-management-views/sys-dm-pdw-request-steps-transact-sql?toc=/azure/synapse-analytics/sql-data-
warehouse/toc.json&bc=/azure/synapse-analytics/sql-data-warehouse/breadcrumb/toc.json&view=azure-sqldw-latest
--------------------------------------------
-- コンピュートノード間でのデータ移動を確認
--------------------------------------------
-- 完了した対象のクエリの QID を確認
SELECT *
FROM sys.dm_pdw_exec_requests
WHERE status in ('Completed','Failed','Cancelled')
AND session_id <> session_id()
ORDER BY submit_time DESC;
-- 分散実行プランでデータ移動が大量に発生していないか確認
-- (BroadcastMoveOperation, ShuffleMoveOperation が対象)
DECLARE @qid VARCHAR(20) = ’QIDxxxxxx’;
SELECT * FROM sys.dm_pdw_request_steps
WHERE request_id = @qid
ORDER BY step_index;