質問
私は今日書いたクエリを使っていました。
item_desc = 'item 1'
OR item_desc = 'item 2'
OR item_desc = 'item 3'
OR item_desc = 'item 4'
.
上記は15分間走り、何も戻っていませんが、次は1.5分で私の結果セットを私に与えました
item_desc IN (
'item 1'
,'item 2'
,'item 3'
,'item 4'
)
.
私はこれをSQLでしました、そしてなぜIN(アイテムのリスト)がそんなに速く実行されたのか、それとも声明を実行するのか疑問に思います。
- 編集 - SQL Server 2008、私は最初の場所でこのビットを入力しないことをお詫び申し上げます。
これは、WHERE
ステートメントを使用してその全体のクエリです。
DECLARE @SD DATETIME
DECLARE @ED DATETIME
SET @SD = '2013-06-01';
SET @ED = '2013-06-15';
-- COLUMN SELECTION
SELECT PV.PtNo_Num AS 'VISIT ID'
, PV.Med_Rec_No AS 'MRN'
, PV.vst_start_dtime AS 'ADMIT'
, PV.vst_end_dtime AS 'DISC'
, PV.Days_Stay AS 'LOS'
, PV.pt_type AS 'PT TYPE'
, PV.hosp_svc AS 'HOSP SVC'
, SO.ord_no AS 'ORDER NUMBER'
--, SO.ent_dtime AS 'ORDER ENTRY TIME'
--, DATEDIFF(HOUR,PV.vst_start_dtime,SO.ent_dtime) AS 'ADM TO ENTRY HOURS'
, SO.svc_desc AS 'ORDER DESCRIPTION'
, OSM.ord_sts AS 'ORDER STATUS'
, SOS.prcs_dtime AS 'ORDER STATUS TIME'
, DATEDIFF(DAY,PV.vst_start_dtime,SOS.prcs_dtime) AS 'ADM TO ORD STS IN DAYS'
-- DB(S) USED
FROM smsdss.BMH_PLM_PtAcct_V PV
JOIN smsmir.sr_ord SO
ON PV.PtNo_Num = SO.episode_no
JOIN smsmir.sr_ord_sts_hist SOS
ON SO.ord_no = SOS.ord_no
JOIN smsmir.ord_sts_modf_mstr OSM
ON SOS.hist_sts = OSM.ord_sts_modf_cd
-- FILTER(S)
WHERE PV.Adm_Date BETWEEN @SD AND @ED
AND SO.svc_cd = 'PCO_REMFOLEY'
OR SO.svc_cd = 'PCO_INSRTFOLEY'
OR SO.svc_cd = 'PCO_INSTFOLEY'
OR SO.svc_cd = 'PCO_URIMETER'
AND SO.ord_no NOT IN (
SELECT SO.ord_no
FRROM smsdss.BMH_PLM_PtAcct_V PV
JOIN smsmir.sr_ord SO
ON PV.PtNo_Num = SO.episode_no
JOIN smsmir.sr_ord_sts_hist SOS
ON SO.ord_no = SOS.ord_no
JOIN smsmir.ord_sts_modf_mstr OSM
ON SOS.hist_sts = OSM.ord_sts_modf_cd
WHERE OSM.ord_sts = 'DISCONTINUE'
AND SO.svc_cd = 'PCO_REMFOLEY'
OR SO.svc_cd = 'PCO_INSRTFOLEY'
OR SO.svc_cd = 'PCO_INSTFOLEY'
OR SO.svc_cd = 'PCO_URIMETER'
)
ORDER BY PV.PtNo_Num, SO.ord_no, SOS.prcs_dtime
.
ありがとう、
解決
オリセキの答えが正しくありません。 SQL Server 2008の場合、IN
リストは一連のOR
ステートメントにリファクタリングされます。 MySQLとは異なる場合があります。
私はあなたがあなたの両方のクエリのための実際の実行計画を生成した場合、それらが同一になるでしょう。
2番目のクエリはを実行し、最初のクエリは既にデータベースからすべてのデータページを引っ張ってioコストを支払っていました。 2番目のクエリは、メモリからすべてのデータを読み取り、高速に実行できました。
更新
差異の実際の源は、クエリがではないのである可能性があります。以下の2つの異なるOR
リストがあります。
WHERE PV.Adm_Date BETWEEN @SD AND @ED
AND SO.svc_cd = 'PCO_REMFOLEY'
OR SO.svc_cd = 'PCO_INSRTFOLEY'
OR SO.svc_cd = 'PCO_INSTFOLEY'
OR SO.svc_cd = 'PCO_URIMETER'
.
以降
WHERE OSM.ord_sts = 'DISCONTINUE'
AND SO.svc_cd = 'PCO_REMFOLEY'
OR SO.svc_cd = 'PCO_INSRTFOLEY'
OR SO.svc_cd = 'PCO_INSTFOLEY'
OR SO.svc_cd = 'PCO_URIMETER'
.
これらのWHERE
句では、演算子の処置(前または)エンジンによって実行される実際の論理が次のとおりです。
WHERE (ConditionA AND ConditionB)
OR ConditionC
OR ConditionD
OR ConditionE
.
OR
リストをIN
式に置き換えると、論理は次のようになります。
WHERE ConditionA
AND (ConditionB OR ConditionC OR ConditionD OR ConditionE)
.
根本的に異なる
他のヒント
EXPLAIN
のようなものを使用して実際のクエリプランを見ることです。これにより、DBMSが何をしているのか正確に言うべきであり、それからそれがそれがより効率的である理由をはるかに良い考えを得ることができます。
それが言うと、DBMSシステムは2つのテーブル(結合のような)間の操作を行うのが本当に良好です。それらは一般的により高価であるので、多くのオプティマイザの時間がクエリのこれらの部分に費やされます。
たとえば、DBMSは、IN
リストをソートし、item_desc
のインデックスを使用して結果を非常に迅速にフィルタリングすることができます。最初の例のような選択の束を一覧表示するときは、その最適化を行うことはできません。
IN
を使用すると、これらのより効率的な表結合技術を使用して即興テーブルとフィルタリングを行います。
edit :OPが特定のDBMSを述べる前にこの回答を投稿しました。これは、SQL Serverがこのクエリをどのように扱うかではないが、他のDBMSシステムに対して有効である可能性があります。 jnkの答えより具体的で正確な答え。