今回の課題
クエリ最適化の英語の記事があったので、
英語の勉強も含めて要約した。
※参考:SQL Query Optimization Techniques
1,テーブルの中から特定の要素を見つける場合、COUNT()
の代わりにEXISTS()
を使う
COUNT()
を使用すると、全量スキャンになってしまい非効率。
一方、EXISTS()
は、特定の要素を見つけた段階でスキャンが止まる。
そのため、クエリの実行時間を節約することができる。
⭕推奨
select
exists(
select
*
from
table
where
element_column = 'val'
)
❌非推奨
select
count(*)
from
table
where
element_column = 'val'
2,Char
の代わりにVarchar
を使用する
char
とvarchar
はテーブルの文字列の型として使われる。
しかし、varchar
はchar
よりもメモリ効率がかなり良い。
char
型は指定した固定長の文字列のみを格納できる。もし、指定した文字列よりも短い文字数だった場合、指定した文字数との差分の量、メモリに無駄が生じる。
一方varchar
型は、指定された最大長以下の可変長の文字列を格納できる。格納された文字数に応じてメモリを消費するので、メモリに無駄が生じない。
3,WHERE句ではサブクエリを避ける
サブクエリが大量の行を返す場合、コストが高くなり実行が困難になる。
サブクエリを使用する代わりに、JOINを使って同じ結果を得ることができる。
⭕推奨
select
orders.*
from
orders
join customers -- customersテーブルと、顧客idをキーにしてinner join結合
on orders.customer_id = customers.id
where
customers.country = 'INDIA'
;
❌非推奨
select
*
from
orders
where -- サブクエリでcountryがINDIAの場合の顧客のidを抽出している
customer_id in (select id from customers where country = 'INDIA')
;
4,大テーブルから小テーブルに向ってJOIN(結合)するようにする
そのように結合するとSQLの実行が速くなる。
理由としては、小テーブルから大テーブルに結合すると、SQLエンジンは大テーブルからマッチする行を探さなければいけない。
一方、大テーブルから小テーブルに結合すると、小テーブルからマッチする行を探すため効率が良い。
⭕推奨
select
*
from
BigTable as b
left join SmallTable as s
on b.id = s.id
5,Like
句の代わりにregexp_like
(正規表現での曖昧検索)を使用する
Like
句は特定の値を探すのにデータベースを全量スキャンしなければならなく、大きいテーブルだと時間がかかってしまう。
一方、regexp_like
は効率的で、正規表現を使って複雑なパターンの値を探すことができる。Like
のようなシンプルなワイルドカードマッチングよりも正確に特定の値を見つけられるので、検索すべきデータ量が減り、クエリの実行速度が速くなる。
⭕推奨
select
*
from
table
where
regexp_like(name, '^[AB].*')
;
❌非推奨
select
*
from
table
where
(
name like 'A%'
or name like 'B%'
)