2016-11-15 18 views
1

以下の症状は弊社に迷惑をかけています。その原因とその解決方法について、皆様のアドバイスをいただければ幸いです。Oracleでの低速クエリ(SQL Serverで高速実行)(相関サブクエリ)

私は以下の単純なクエリを実行しました。同じテーブルを持つSQL Serverデータベースで同じクエリが数秒で完了する間に、Oracle DBが結果を返すのに3,800秒かかりました。 (これはデータマートとして使用されます)。

問合せ:

select 
T_X.Col1 
,(select count(1) from T_X where T_X.colX = T_Y.colY) as cnt1 
from T_Y 

レコードカウント:

T_X:96536

T_Y:129359

その他の情報:

-ColYはT_Yの主キーであり、2つの環境の両方でColXinにインデックスがありません。

-oracle 11.1(SQL Developerを使用してクエリを実行した)

-SQL Server 2008には、2つの環境間のハードウェアスペックの大きな違い-NO

を(SSMSを使用してクエリを実行しました)。

-上記のクエリは、より大きなものの一部です。私たちはそれを単純化し、その部分がボトルネックであることを見出しました。

ご連絡ありがとうございます。

追加情報(クエリの目的)上記

クエリは以下のクエリの一部です。私たちの目的は、他のテーブル(T_A、T_B、T_C、T_D、T_E、T_X)に対応するレコードを持たないT_Yのレコードの数(カウント)を調べることです。

select   
    count(1)   
from    
    (select 
    T_Y.ColA 
    ,T_Y.ColG 
    ,T_Y.ColH 
    ,(select count(1) from T_A A where A.ColA = T_Y.ColY) as cnt1 
    ,(select count(1) from T_B B where B.ColB = T_Y.ColY) as cnt2 
    ,(select count(1) from T_X where T_X.ColX = T_Y.ColY) as cnt3 
    ,(select count(1) from T_C C where C.ColC = T_Y.ColY) as cnt4 
    ,(select count(1) from T_D D where D.ColD = T_Y.ColY) as cnt5 
    ,(select count(1) from T_E E where E.ColE = T_Y.ColY) as cnt6 
    from T_Y 
)XXX 
where 1=1 
    and XXX.ColH in ('X') 
    and XXX.cnt1 = 0 
    and XXX.cnt2 = 0 
    and XXX.cnt3 = 0 
    and XXX.cnt4 = 0 
    and XXX.cnt5 = 0 
    and XXX.cnt6 = 0 
;   

実行計画 - オラクル(元のクエリのための)(実行計画の実行)

"Optimizer" "Cost" "Cardinality" "Bytes" "Partition Start" "Partition Stop" "Partition Id" "ACCESS PREDICATES" "FILTER PREDICATES" 
"SELECT STATEMENT" "ALL_ROWS" "121" "129359" "776154" "" "" "" "" "" 
"SORT(AGGREGATE)" "" "" "1" "6" "" "" "" "" "" 
"TABLE ACCESS(FULL) XXXXX.T_X" "ANALYZED" "6616" "2" "12" "" "" "" "" ""T_X"."ColX"=:B1" 
"INDEX(FAST FULL SCAN) XXXXX.T_Y_0" "ANALYZED" "121" "129359" "776154" "" "" "" "" "" 

実行計画 - (元のクエリのための)SQL Serverの

7行目クラスタードインデックスにはColumnYが含まれていませんが、SQL Serverはテーブルスキャンの代わりにクラスタードインデックススキャンを使用しています。誰でもこれが何を意味するのか説明できますか? Oracleに、ヒント句などを使用して同様の実行計画を使用させることができますか?

|--Compute Scalar(DEFINE:([Expr1008]=CASE WHEN [Expr1006] IS NULL THEN (0) ELSE [Expr1006] END)) 
     |--Parallelism(Gather Streams) 
      |--Hash Match(Right Outer Join, HASH:([DB_X].[dbo].[T_X].[ColX])=([DB_X].[dbo].[T_Y].[ColY]), RESIDUAL:([DB_X].[dbo].[T_X].[ColX]=[DB_X].[dbo].[T_Y].[ColY])) 
       |--Compute Scalar(DEFINE:([Expr1006]=CONVERT_IMPLICIT(int,[Expr1013],0))) 
       | |--Hash Match(Aggregate, HASH:([DB_X].[dbo].[T_X].[ColX]), RESIDUAL:([DB_X].[dbo].[T_X].[ColX] = [DB_X].[dbo].[T_X].[ColX]) DEFINE:([Expr1013]=COUNT(*))) 
       |   |--Parallelism(Repartition Streams, Hash Partitioning, PARTITION COLUMNS:([DB_X].[dbo].[T_X].[ColX])) 
       |    |--Clustered Index Scan(OBJECT:([DB_X].[dbo].[T_X].[PK_T_X])) 
       |--Parallelism(Repartition Streams, Hash Partitioning, PARTITION COLUMNS:([DB_X].[dbo].[T_Y].[ColY])) 
         |--Clustered Index Scan(OBJECT:([DB_X].[dbo].[T_Y].[PK_T_Y])) 
+0

あなたのクエリが混乱しています。あなたの意図が何であるかを言葉で説明します。 –

+0

修正:colYはT_Yの主キーです。 – yobioo

+0

両方のデータベースにクエリの実行計画を掲載してください。 – sstan

答えて

0

私たちの目的は、他のテーブル(T_A、T_B、T_C、T_D、T_E、T_X)に対応するレコードを持っていませんT_Yのレコードを(の数)を見つけることです。より良いように表現されるだろう

select   
    count(*)   
from    
    T_Y 
where ColH in ('X') and 
     not exists (select null from T_A A where A.ColA = T_Y.ColY) and 
     not exists (select null from T_B B where B.ColB = T_Y.ColY) and 
     not exists (select null from T_X where T_X.ColX = T_Y.ColY) and 
     not exists (select null from T_C C where C.ColC = T_Y.ColY) and 
     not exists (select null from T_D D where D.ColD = T_Y.ColY) and 
     not exists (select null from T_E E where E.ColE = T_Y.ColY); 
+0

David、解決に感謝します!あなたのSQLはわずか2分でキャッシュをクリアして結果を取得しました。 – yobioo

0

あなたはt_x(colX)にインデックスを必要とします。私はこのインデックスがSQL Server上に存在すると推測しています。

このバージョンでは、いずれかのマシンに速いかもしれません:

select t_x.colX, count(1) 
from T_X 
group by t_x.colX; 

それはまったく同じではありませんが、それはあなたが本当に欲しいものであるかもしれません。

+0

コメントありがとう!元の投稿を修正したので、colYはT_Yの主キーでした。ただし、2つの環境はキーとインデックスについて同じ条件を共有します。 – yobioo

+0

インデックスを追加するとうまくいくと思いますが、DBがパッケージソフトウェアの一部であるため、オブジェクトの定義を変更することはできません。私はそれが定義に何の変更もなしにSQL Serverでうまくいくと思ったが、なぜOracleにはないのだろうか。 – yobioo

+0

これは、SQL ServerがOracleよりもクエリを最適化する場合がありますが、それは私には驚きです。 Oracleは通常、この種の問合せではかなり優れています。 –

関連する問題