『INDEX』のキホンで、否定条件(NOT IN等)はINDEXが効かず性能的に使用は避けるべきと書きました。
確かに「NOT IN」より「NOT EXISTS」を使うべきだとされていることもありますが、しかし昨今のRDBでは、何かと最適化もされているので実のところどうなのでしょうか・・・
この他にも「LEFT JOIN + IS NULL」も代用できますが、これらの違いを各RDBでの性能の違いを検証してみました。
検証用テーブル
『JOIN と SELECT列のサブクエリー』で使ったテーブルを使用しました。
出力内容
製品マスタで、まだ受注されていない製品を抽出する。
求めたい表イメージ
・・・ | ・・・ |
PRODUCT_ID | PRODUCT_NAME |
P003001 | 製品名3001 |
P003002 | 製品名3002 |
P003005 | 製品名3005 |
抽出結果が2000件。(未受注製品が2000件)
PRODUCT_IDは必須値。
①「NOT IN」で求める
select p.PRODUCT_ID, p.PRODUCT_NAME from M_PRODUCT p where p.PRODUCT_ID not in(select PRODUCT_ID from T_ORDER) order by p.PRODUCT_ID |
②「NOT EXISTS」で求める
select p.PRODUCT_ID, p.PRODUCT_NAME from M_PRODUCT p where not exists(select * from T_ORDER o where p.PRODUCT_ID = o.PRODUCT_ID) order by p.PRODUCT_ID |
③「LEFT JOIN + IS NULL」で求める
select p.PRODUCT_ID, p.PRODUCT_NAME from M_PRODUCT p left join T_ORDER o ON p.PRODUCT_ID = o.PRODUCT_ID where o.PRODUCT_ID is null order by p.PRODUCT_ID |
結果
今回の測定結果では、以下の通り、サーバ系では性能差がないという結果となり、AccessDBは、大きな性能差が生じる結果となりました。
単位:秒
NOT IN | NOT EXISTS | LEFT JOIN + IS NULL | |
postgresql-9.6 | 0.055 | 0.060 | 0.057 |
MySQL15.1 | 0.048 | 0.049 | 0.047 |
Oracle11g(XE) | 0.037 | 0.051 | 0.058 |
SQLServer2016(Expless) | 0.061 | 0.050 | 0.060 |
Access2016 | 773.536 | 0.048 | 0.587 |
以下のRDBで「実行計画」の違いを確認したところ・・・
postgresql・・・「NOT EXISTS」と「LEFT JOIN + IS NULL」が同じ
MySQL・・・「NOT IN」と「NOT EXISTS」が同じ
Oracle・・・全て同じ
今回の結果では、サーバー系RDBでは、性能差に違いが生じることはなく、オプティマイザが最適な実行計画を選択できたのかと思います。
DBのバージョンやテーブルやデータの状態にもより必ずしも最適に選択されないことも考えられるので注意は必要だと思いますが、「NOT IN」はスッキリとした書き方ではあるので、これらのRDBでは性能や実行計画を確認しながら使ってみてもいいのかも知れません。
AcccessDBについては、この通り性能的に使用すべきではない結果となり、また「NOT IN や「IN」では複数カラムの指定もできないので、「NOT EXISTS(EXISTS)」しておくのが適切な選択だと言えるかと思います。
今回の結果では「LEFT JOIN + IS NULL」は、何れのRDBでも特にメリットがない結果になりました。
また、複数条件の場合、INDEXの掛かり方等で性能差は出てくると思うので、何処かで改めて検証できればと思います。
We arе a grouⲣ օf volunteers and starting a new scheme in ⲟur community.
Yоur web site offered us wіth ᥙseful info to work on. You
have ɗone an impressive process аnd oսr entire neighborhood
wіll ρrobably Ƅe thankful to yoս.
Thanks Rhea.
I am pleased that you helps.