クエリ調整用の診断クエリ - Amazon Redshift

クエリ調整用の診断クエリ

クエリや基礎となるテーブルの、クエリパフォーマンスに影響を与える可能性がある問題を特定するには、次のクエリを使用します。これらのクエリは、「クエリの分析および改善」で説明されているクエリ調整プロセスと同時に使用することをお勧めします。

優先して調整が必要なクエリの特定

以下のクエリは、過去 7 日間に実行されたステートメントのうち、最も時間がかかった上位 50 位のステートメントを特定します。この結果を利用することで、異常に時間がかかっているクエリを特定できます。また、頻繁に実行されるクエリ (結果セットに複数回出現するクエリ) を特定できます。これらのクエリは多くの場合、システムパフォーマンスを高めるために優先して調整する必要があります。

このクエリは、特定された各クエリに関連するアラートイベントの数も生成します。これらのアラートは、クエリのパフォーマンスを高めるために使用できる詳細を提供します。詳細については、「クエリアラートの確認」を参照してください。

select trim(database) as db, count(query) as n_qry, max(substring (qrytext,1,80)) as qrytext, min(run_minutes) as "min" , max(run_minutes) as "max", avg(run_minutes) as "avg", sum(run_minutes) as total, max(query) as max_query_id, max(starttime)::date as last_run, sum(alerts) as alerts, aborted from (select userid, label, stl_query.query, trim(database) as database, trim(querytxt) as qrytext, md5(trim(querytxt)) as qry_md5, starttime, endtime, (datediff(seconds, starttime,endtime)::numeric(12,2))/60 as run_minutes, alrt.num_events as alerts, aborted from stl_query left outer join (select query, 1 as num_events from stl_alert_event_log group by query ) as alrt on alrt.query = stl_query.query where userid <> 1 and starttime >= dateadd(day, -7, current_date)) group by database, label, qry_md5, aborted order by total desc limit 50;

データスキューまたは未ソート行のあるテーブルの特定

次のクエリは、データ分散が均等でない (データスキュー) テーブルや、未ソート行の割合が多いテーブルを特定します。

skew 値が小さい場合、テーブルデータが適切に分散されていることを示します。テーブルの skew 値が 4.00 以上の場合、データ分散スタイルを変更することを検討してください。詳細については、「十分最適でないデータ分散」を参照してください。

テーブルの pct_unsorted 値が 20 パーセントを超える場合、VACUUMコマンドの実行を検討します。詳細については、「未ソート行または正しくソートされていない行」を参照してください。

各テーブルの mbytes 値と pct_of_total 値も見直してください。これらの列は、テーブルのサイズと、raw ディスクスペースに対してテーブルが消費しているスペースの割合を示します。raw ディスク容量には、Amazon Redshift が内部用に予約するスペースの分も含まれます。このため、ユーザーが利用できるディスク容量として表示される名目上のディスク容量より大きな数字になります。この情報をもとに、最も大きいテーブルの 2.5 倍以上の空きディスク容量があることを確認します。このスペースがあれば、システムは複雑なクエリの処理時に中間結果をディスクに書き込むことができます。

select trim(pgn.nspname) as schema, trim(a.name) as table, id as tableid, decode(pgc.reldiststyle,0, 'even',1,det.distkey ,8,'all') as distkey, dist_ratio.ratio::decimal(10,4) as skew, det.head_sort as "sortkey", det.n_sortkeys as "#sks", b.mbytes, decode(b.mbytes,0,0,((b.mbytes/part.total::decimal)*100)::decimal(5,2)) as pct_of_total, decode(det.max_enc,0,'n','y') as enc, a.rows, decode( det.n_sortkeys, 0, null, a.unsorted_rows ) as unsorted_rows , decode( det.n_sortkeys, 0, null, decode( a.rows,0,0, (a.unsorted_rows::decimal(32)/a.rows)*100) )::decimal(5,2) as pct_unsorted from (select db_id, id, name, sum(rows) as rows, sum(rows)-sum(sorted_rows) as unsorted_rows from stv_tbl_perm a group by db_id, id, name) as a join pg_class as pgc on pgc.oid = a.id join pg_namespace as pgn on pgn.oid = pgc.relnamespace left outer join (select tbl, count(*) as mbytes from stv_blocklist group by tbl) b on a.id=b.tbl inner join (select attrelid, min(case attisdistkey when 't' then attname else null end) as "distkey", min(case attsortkeyord when 1 then attname else null end ) as head_sort , max(attsortkeyord) as n_sortkeys, max(attencodingtype) as max_enc from pg_attribute group by 1) as det on det.attrelid = a.id inner join ( select tbl, max(mbytes)::decimal(32)/min(mbytes) as ratio from (select tbl, trim(name) as name, slice, count(*) as mbytes from svv_diskusage group by tbl, name, slice ) group by tbl, name ) as dist_ratio on a.id = dist_ratio.tbl join ( select sum(capacity) as total from stv_partitions where part_begin=0 ) as part on 1=1 where mbytes is not null order by mbytes desc;

ネステッドループにあるクエリの特定

次のクエリは、ネステッドループに関して記録されたアラートイベントを持つクエリを特定します。ネステッドループ状態を修正する方法については、「Nested Loop」を参照してください。

select query, trim(querytxt) as SQL, starttime from stl_query where query in ( select distinct query from stl_alert_event_log where event like 'Nested Loop Join in the query plan%') order by starttime desc;

クエリのキュー待機時間の確認

以下のクエリでは、最近のクエリが、実行される前にクエリキューで空きスロットを待機していた時間の長さが示されます。待機時間が長い傾向が見られる場合、スループットを高めるためにクエリキュー設定を変更できます。詳細については、「手動 WLM を実装する」を参照してください。

select trim(database) as DB , w.query, substring(q.querytxt, 1, 100) as querytxt, w.queue_start_time, w.service_class as class, w.slot_count as slots, w.total_queue_time/1000000 as queue_seconds, w.total_exec_time/1000000 exec_seconds, (w.total_queue_time+w.total_Exec_time)/1000000 as total_seconds from stl_wlm_query w left join stl_query q on q.query = w.query and q.userid = w.userid where w.queue_start_Time >= dateadd(day, -7, current_Date) and w.total_queue_Time > 0 and w.userid >1 and q.starttime >= dateadd(day, -7, current_Date) order by w.total_queue_time desc, w.queue_start_time desc limit 35;

テーブルごとのクエリアラートの確認

次のクエリは、アラートイベントが記録されたテーブルを特定します。また、最も頻繁に発生したアラートの種類も特定します。

特定されたテーブルの行の minutes 値が大きい場合、そのテーブルで、ANALYZEVACUUM を実行するなどの定期的なメンテナンスが必要かどうかを確認します。

行の count 値が大きいが table が null の場合、関連する event 値の STL_ALERT_EVENT_LOG に対してクエリを実行し、そのアラートが頻繁に派生する理由を調査します。

select trim(s.perm_table_name) as table, (sum(abs(datediff(seconds, s.starttime, s.endtime)))/60)::numeric(24,0) as minutes, trim(split_part(l.event,':',1)) as event, trim(l.solution) as solution, max(l.query) as sample_query, count(*) from stl_alert_event_log as l left join stl_scan as s on s.query = l.query and s.slice = l.slice and s.segment = l.segment and s.step = l.step where l.event_time >= dateadd(day, -7, current_Date) group by 1,3,4 order by 2 desc,6 desc;

統計がないテーブルの特定

次のクエリは、統計がないテーブルに対して実行中のクエリの数を示します。このクエリが任意の行を返す場合、plannode値を調べて影響を受けるテーブルを特定した後、そのテーブルで ANALYZE を実行します。

select substring(trim(plannode),1,100) as plannode, count(*) from stl_explain where plannode like '%missing statistics%' group by plannode order by 2 desc;