Oracle中的慢查询(在SQL Server中快速运行)(相关子查询)

时间:2016-11-15 01:21:07

标签: sql sql-server oracle

我们对以下症状感到恼火。我们非常感谢您就其原因及解决方法提出的任何建议。

我运行下面的简单查询,Oracle DB需要3,800秒才能返回结果,而同一查询在几秒钟内在具有相同表的SQL Server数据库中完成。 (它用作数据集市)。

查询:

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

记录次数:

T_X:96,536

T_Y:129,359

其他信息:

-ColY是T_Y的主键,两个环境中的ColXin都没有索引。

-Oracle 11.1(使用SQL Developer运行查询)

-SQL Server 2008(使用SSMS运行查询)

- 两种环境之间的硬件规格差异不大。

- 上面的查询是较大的一部分。我们对其进行了简化,发现该部分是瓶颈。

我们非常感谢您的建议!

其他信息(查询的目的)

上面的查询是下面查询的一部分。我们的目的是找出T_Y中的记录(计数),这些记录在其他表中没有对应的记录(T_A,T_B,T_C,T_D,T_E,T_X)。

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
;           

执行计划 - Oracle(原始查询)(执行解释计划)

"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行表示SQL Server使用Clustered Index Scan而不是Table Scan,尽管聚簇索引不包含ColumnY。有谁能解释这是什么意思? 我是否可以强制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]))

2 个答案:

答案 0 :(得分:0)

您需要t_x(colX)上的索引。我猜这个索引存在于SQL Server上。

这两个版本的版本可能更快:

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

它不完全相同,但它可能是你真正想要的。

答案 1 :(得分:0)

  

我们的目的是找出T_Y中的记录(计数)在其他表中没有对应记录(T_A,T_B,T_C,T_D,T_E,T_X)。

最好表达为:

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);