初級者向けSQLチューニング練習問題を
- チューニング対象 SQL 文
- SQL 文を実行するためのテーブルとデータの作成スクリプト
のペアで作成しました。以下で公開しています。
私自身は最近 BI/DWH を中心としたデータ分析系システムを担当することが多いので、OLTP 系システムの SQL チューニングに関わることはほとんどありません。ただ、会社で DB を学び始めた人の育成に関わることもあり、その一環で初歩的な SQL チューニングに取り組める環境を準備しておこうと思い、この問題を作りました。
テーブル構造やチューニング対象の SQL 文は意図的に非常にシンプルにしてあります。そのため、適当に試行錯誤することで速くすることができるかもしれませんが、実行計画の取得の方法やその解釈、遅い原因の特定などチューニングに必要なプロセスを経験することを意識して取り組んでもらえればと思います。
ちなみに今回準備したチューニング対象 SQL 文は、大半が ChatGPT に SQL チューニングさせてみた以下の記事のものを再利用しています。
上の記事にあるように ChatGPT でも概ね適切なチューニング案を提示できるのですが、その結果の妥当性を判断するためには実行計画の分析方法や主要なチューニング手法について知っている必要があります。そういったものを実践で学び始める第一歩になればと思っています。
環境構築の方法や練習問題に取り組みにあたっての注意点はリポジトリをご確認ください。
以下に対象の SQL 文を載せておきます。
select
c.customer_id,
c.customer_name
from
customers c
where
c.tel_number = '09012345678'
;
select
i.item_id,
i.item_name
from
items i
where
i.item_category_id = 30230
and
i.supplier_id = 40620
;
select
count(*)
from
customers c
where
to_char(c.birthday, 'YYYYMM') = '200101'
;
select
c.customer_id,
c.customer_name
from
customers c
where
c.region_cd = 200123
;
select
count(*)
from
orders o
where
o.order_date between
to_date('2023-04-01', 'YYYY-MM-DD') and
to_date('2023-06-30', 'YYYY-MM-DD')
and
o.item_id = 20000034
;
select
o.order_id,
o.order_date,
o.item_id,
o.order_amount
from
orders o
inner join
customers c on (o.customer_id = c.customer_id)
where
c.customer_name = 'cust_name_10064248'
order by
o.order_id
;
select
o.order_id,
c.customer_name,
i.item_name
from
orders o
inner join
customers c on (o.customer_id = c.customer_id)
inner join
items i on (o.item_id = i.item_id)
where
c.prefecture_cd = 14
and
i.item_name like 'item\_ABCDEFGHIJKLMNOP\_2299999%' escape '\'
;
select
o.order_id,
o.order_date,
o.item_id,
o.order_quantity
from
orders o
where
o. customer_id = 10000128
order by
o.order_date desc
fetch first 50 rows only
;
select
o.order_date,
sum(o.order_quantity),
sum(o.order_amount)
from
orders o
where
o.item_id = 20000301
group by
o.order_date
;
select
c.customer_id,
o.order_id,
o.item_id
from
customers c
inner join
orders o on (c.customer_id = o.customer_id)
where
c.customer_name like 'cust\_name\_1000001%' escape '\'
and
o.order_id = (
select
max(o1.order_id)
from
orders o1
where
o1.customer_id = c.customer_id
)
order by
c.customer_id
;