

 Amazon Redshift は、パッチ 198 以降、新しい Python UDF の作成をサポートしなくなります。既存の Python UDF は、2026 年 6 月 30 日まで引き続き機能します。詳細については、[ブログ記事](https://aws.amazon.com/blogs/big-data/amazon-redshift-python-user-defined-functions-will-reach-end-of-support-after-june-30-2026/)を参照してください。

# クエリ調整用の診断クエリ
<a name="diagnostic-queries-for-query-tuning"></a>

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

**注記**  
これらのクエリは Amazon Redshift でプロビジョニングされたクラスター用です。これらのクエリは Redshift Serverless ワークグループでは使用できません。

**Topics**
+ [優先して調整が必要なクエリの特定](identify-queries-that-are-top-candidates-for-tuning.md)
+ [データスキューまたは未ソート行のあるテーブルの特定](identify-tables-with-data-skew-or-unsorted-rows.md)
+ [ネステッドループにあるクエリの特定](identify-queries-with-nested-loops.md)
+ [クエリのキュー待機時間の確認](review-queue-wait-times-for-queries.md)
+ [テーブルごとのクエリアラートの確認](review-query-alerts-by-table.md)
+ [統計がないテーブルの特定](identify-tables-with-missing-statistics.md)

# 優先して調整が必要なクエリの特定
<a name="identify-queries-that-are-top-candidates-for-tuning"></a>

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

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

```
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;
```

# データスキューまたは未ソート行のあるテーブルの特定
<a name="identify-tables-with-data-skew-or-unsorted-rows"></a>

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

`skew` 値が小さい場合、テーブルデータが適切に分散されていることを示します。テーブルの `skew` 値が 4.00 以上の場合、データ分散スタイルを変更することを検討してください。詳細については、「[十分最適でないデータ分散](query-performance-improvement-opportunities.md#suboptimal-data-distribution)」を参照してください。

テーブルの `pct_unsorted` 値が 20 パーセントを超える場合、[VACUUM](r_VACUUM_command.md)コマンドの実行を検討します。詳細については、「[未ソート行または正しくソートされていない行](query-performance-improvement-opportunities.md#unsorted-or-mis-sorted-rows)」を参照してください。

各テーブルの `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;
```

# ネステッドループにあるクエリの特定
<a name="identify-queries-with-nested-loops"></a>

次のクエリは、ネステッドループに関して記録されたアラートイベントを持つクエリを特定します。ネステッドループ状態を修正する方法については、「[Nested Loop](query-performance-improvement-opportunities.md#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;
```

# クエリのキュー待機時間の確認
<a name="review-queue-wait-times-for-queries"></a>

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

```
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;
```

# テーブルごとのクエリアラートの確認
<a name="review-query-alerts-by-table"></a>

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

特定されたテーブルの行の `minutes` 値が大きい場合、そのテーブルで、[ANALYZE](r_ANALYZE.md)や [VACUUM](r_VACUUM_command.md) を実行するなどの定期的なメンテナンスが必要かどうかを確認します。

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

```
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;
```

# 統計がないテーブルの特定
<a name="identify-tables-with-missing-statistics"></a>

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

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