fc2ブログ

記事一覧

IN 句と EXISTS 句で実行速度が速いのはどちらの方か検証してみました | SQL Server


今回は SQL Server において IN 句と EXISTS 句でどちらが実行速度が速いのかを調査・検証してみました。
通常 INNER JOIN (等価結合)が一番速いという事は誰もが認識されていると思いますが、IN 句は遅く、EXISTS 句は速いという事が RDB の通説と言われていますが、SQL Server ではその実行速度が同じという事を聞きましたので、改めまして検証してみたいと思います。


前提条件
・Windows10 Pro 64Bit 1709
・SQL Server 2016 Developer / Standard / Enterprise 以降



1.検証用のテーブル

検証用のテーブルを用意します。今回は手軽に12万件の大量のデータを作成できることから、以下の郵便局の郵便番号の CSV データを SQLServer にインポートしてパフォーマンスが出ないようにわざとインデックスを作成せずに使用してみます。
https://www.post.japanpost.jp/zipcode/dl/kogaki/zip/ken_all.zip

sql_in_exists_inner_00.png


さらに、12万件では1秒以内に結果が返ってしまいましたので、同じデータを同じテーブルに INSERT してデータ量を200万件まで水増しします。

sql_in_exists_inner_01.png



2.検証用のSQL

以下のように全ての実行結果が同じになる3種類の SQL を用意します。予めKEN_ALL のデータを郵便番号と都道府県で DISTINCT したデータを KEN テーブルに作成しておきます。KEN_ALL テーブルは約200万件、KEN テーブルは約12万件、両者のテーブルを結合すると約12万件のデータとなります。
いずれも、北海道という名称を含まない都道府県に紐づく郵便番号のみで絞り、結果を DISTINCT していますので約11万6000件の実行結果となります。


(1)IN 句を使用したSQL実行例
USE [testDB]
GO

SELECT DISTINCT
*
FROM [testDB].[dbo].[KEN_ALL] AS KA
WHERE KA.[郵便番号7] IN (
SELECT KEN.[郵便番号7]
FROM KEN
WHERE KEN.[都道府県] NOT LIKE '%北海道%'
)
;


(2)EXISTS 句を使用したSQL実行例
USE [testDB]
GO

SELECT DISTINCT
*
FROM [testDB].[dbo].[KEN_ALL] AS KA
WHERE EXISTS (
SELECT KEN.*
FROM KEN
WHERE KEN.[都道府県] NOT LIKE '%北海道%'
AND KEN.[郵便番号7] = KA.[郵便番号7]
)
;


(3)INNER JOIN (等価結合)を使用したSQL実行例
USE [testDB]
GO

SELECT DISTINCT
*
FROM [testDB].[dbo].[KEN_ALL] AS KA
INNER JOIN
(
SELECT *
FROM KEN
WHERE [都道府県] NOT LIKE '%北海道%'
) AS KEN
ON KEN.[郵便番号7] = KA.[郵便番号7]
;



3.実行結果

3つの SQL による実行結果は以下のようになります。

(1)IN 句   :キャッシュ無し 25秒 → 実行2回目以降 23秒~22秒

sql_in_exists_inner_03.png


(2)EXISTS 句:キャッシュ無し 25秒 → 実行2回目以降 23秒~22秒

sql_in_exists_inner_02.png


(3)INNER JOIN:キャッシュ無し 21秒 → 実行2回目以降 20秒

sql_in_exists_inner_05.png



4.実行速度の結論と考察

以上のことから、SQL Server では IN 句と EXISTS 句の実行速度に違いがないことが分かりました。キャッシュの有無で実行速度に違いはあり、実行する度に経過時間は変化しますが、どちらもおおよそ22秒に収束する事、実行計画(実行プラン)が同じことからも、同じ処理がなされていますので、同じ実行時間となると考えられます。

ただし、他の RDB では同じような実行結果にはなりませんので、IN 句自体の使用は控えておくと DB が変更になってもスムーズに開発や移行ができると思いますので、私自身としましては、EXISTS 句を使用することをお勧めしたいと思います。
また、INNER JOIN では Merge Join にコストがかかるようになっており、実行計画に若干の違いが見受けられます。最速なのはやはり INNER JOIN ですね。
それぞれ、開発の状況に応じて使い分けをする必要があると思いますが、なるべく INNER JOIN > EXISTS > IN の優先順位で使用したいですね。





最後までお読みいただき、ありがとうございます。
他にも SQL Server に関する記事をご紹介しておりますのでご参考頂ければ幸いです。



関連記事

コメント

コメントの投稿

※名前とタイトルが入力されていないコメントでは他のコメントとの区別ができません。

 入力されていないコメントには返信しませんのであらかじめご了承くださいませ。

※ニックネームでも良いので必ずご入力ください。

    

※必ずご入力ください。

    
    

※必ずご入力ください。

※技術的な質問には環境やエラーについて正確かつ詳細にお教えください。

・正確なエラーの内容

・Windowsのバージョン番号

・Visual Studioのバージョン

・機器の型番

・アプリやソフトのバージョン

    

カテゴリ別記事一覧

広告

プロフィール

石河 純


著者名 :石河 純
自己紹介:素人上がりのIT技術者。趣味は卓球・車・ボウリング

IT関連の知識はざっくりとこんな感じです。
【OS関連】
WindowsServer: 2012/2008R2/2003/2000/NT4
Windows: 10/8/7/XP/2000/me/NT4/98
Linux: CentOS RedHatLinux9
Mac: macOS Catalina 10.15 / Mojave 10.14 / High Sierra 10.13 / Sierra 10.12 / OSX Lion 10.7.5 / OSX Snow Leopard 10.6.8
【言語】
VB.net ASP.NET C#.net Java VBA
Xamarin.Forms
【データベース】
Oracle 10g/9i
SQLServer 2016/2008R2/2005/2000
SQLAnywhere 16/11/8
【BI/レポートツール】
Cognos ReportNet (IBM)
Microsoft PowerBI
ActiveReport (GrapeCity)
CrystalReport
【OCX関連】
GrapeCity InputMan SPREAD MultiRow GridView
【ネットワーク関連】
CCNP シスコ技術者認定
Cisco Catalyst シリーズ
Yamaha RTXシリーズ
FireWall関連
【WEB関連】
SEO SEM CSS jQuery IIS6/7 apache2

休みの日は卓球をやっています。
現在、卓球用品通販ショップは休業中です。