【问题标题】:Oracle HASH_JOIN_RIGHT_SEMI performanceOracle HASH_JOIN_RIGHT_SEMI 性能
【发布时间】:2016-05-27 19:50:03
【问题描述】:

这是我的查询,

SELECT si.* FROM 
FROM SHIPMENT_ITEMS si
 WHERE ID IN ( SELECT ID FROM id_map WHERE code = 'A' )
   AND LAST_UPDATED BETWEEN TO_DATE('20150102','YYYYMMDD') - 1 AND TO_DATE('20150103','YYYYMMDD')

SHIPMENT_ITEMS 是一个非常大的表(10.1TB),id_map 是一个非常小的表(12 行和 3 列)。此查询经过 HASH_JOIN_RIGHT_SEMI 并且需要很长时间。SHIPMENT_ITEMS 在 ID 列上进行分区。

如果我删除带有硬编码值的子查询,它的性能会好很多

 SELECT si.* FROM 
    FROM SHIPMENT_ITEMS si
     WHERE ID IN (1,2,3 )
       AND LAST_UPDATED BETWEEN TO_DATE('20150102','YYYYMMDD') - 1 AND TO_DATE('20150103','YYYYMMDD')

我无法删除子查询,因为它会导致硬编码。

鉴于 id_map 是一个非常小的表,我希望这两个查询的执行非常相似。为什么第一个需要更长的时间。

我实际上是想了解为什么它的表现如此糟糕。

我预计动态分区修剪会在这里发生,但我无法找到它为什么没有发生的原因

https://docs.oracle.com/cd/E11882_01/server.112/e25523/part_avail.htm#BABHDCJG

【问题讨论】:

  • IN 的性能非常低,您尝试加入表格吗?还是使用存在?
  • 这将有助于为两个查询添加解释计划以查看它们之间的区别。运行explain plan for select ...;,然后运行select * from table(dbms_xplan.display);,然后在此处发布整个 输出。此外,这些是正在运行的真正查询吗?似乎他们会返回数百万行,这通常没有意义。您是在比较从某个 IDE 返回所有行还是仅返回前 N 行的时间?

标签: sql oracle performance oracle11g database-performance


【解决方案1】:

尝试提示no_unnest

SELECT si.* FROM 
FROM SHIPMENT_ITEMS si
 WHERE ID IN ( SELECT /*+ NO_UNNEST */ ID FROM id_map WHERE code = 'A' )
   AND LAST_UPDATED BETWEEN TO_DATE('20150102','YYYYMMDD') - 1 AND TO_DATE('20150103','YYYYMMDD')

CBO 不会尝试加入子查询并像过滤器一样使用它

【讨论】:

  • 您还可以向 OP 和其他将阅读此提示的人解释此提示的具体作用。
  • hint 表示 CBO 不会尝试加入子查询并像过滤器一样使用它
  • 对我来说,对阅读它的人来说不是。提示:编辑你的问题并写在那里
【解决方案2】:

不要使用'in'运算符,而是使用exists并检查查询性能

SELECT si.* FROM 
FROM SHIPMENT_ITEMS si
 WHERE Exists ( SELECT 1 FROM id_map map WHERE map.code = 'A' and map.ID = so.ID)
   AND LAST_UPDATED BETWEEN TO_DATE('20150102','YYYYMMDD') - 1 AND TO_DATE('20150103','YYYYMMDD')

【讨论】:

    猜你喜欢
    • 2010-12-04
    • 2021-03-13
    • 2016-03-04
    • 2012-02-26
    • 2010-10-27
    • 2016-06-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多