【问题标题】:oracle return all rows from a table iforacle 返回表中的所有行,如果
【发布时间】:2019-04-17 16:55:42
【问题描述】:

对不起,我的描述很糟糕,但问题很容易解释。我有一个名为 BigTable 的大型表(超过 20 亿行),它按日期分区,如下所示:

ID 对象日期 --- -------- ---------- 1个 2018-10-01 1 B 2018-10-01 1 C 2018-10-01 1 天 2018-10-01 2 M 2018-10-01 2 否 2018-10-01 2 O 2018-10-01 3 X 2018-10-01 3 B 2018-10-01

我需要一个 SQL 来返回 ID 的所有行,其中 Object = "B" 和 date = '2018-10-01' 因此结果将是:

ID 对象日期 --- -------- ---------- 1个 2018-10-01 1 B 2018-10-01 1 C 2018-10-01 1 天 2018-10-01 3 X 2018-10-01 3 B 2018-10-01

SQL 很简单,只需将表连接到自身即可:

SELECT t2.id,t2.object, t2.date
FROM BigTable T1
join BigTable T2 on t2.id = t1.id
   AND t2.transaction_date = '01-OCT-2018'
   AND t2.object = 'B'
where t1.date = '01-OCT-2018'

不过,这会持续 HOURS。子查询并没有让它变得更好。 返回包含 object = 'B' 的 ID 的所有行的最有效方法是什么?

【问题讨论】:

  • 使用t2.transaction_date = DATE '2018-10-01't1.date = DATE '2018-10-01' 避免隐式转换。在(date, id, transaction_date, object)上创建一个本地索引
  • @KaushikNayak 你应该把它放在一个答案中,因为隐式类型转换很可能是他真正的问题。
  • 请检查我的答案,如果它对你有用,请接受/投票,这样它也可以帮助其他人寻求答案。请阅读:stackoverflow.com/help/someone-answers
  • 很遗憾,索引已经存在,建议的更改并没有提高性能。

标签: sql oracle performance join


【解决方案1】:

我假设您已经建立了良好的索引...不能保证这会有所帮助,但是您是否尝试过半连接:

select
  t1.*
from BigTable T1
where
  t1.transaction_date = '01-OCT-2018' and
  exists (
    select null
    from BigTable T2
    where
      t2.transaction_date = t1.transaction_date and
      t2.transaction_date = '01-OCT-2018'
      t2.object = 'B'
)

半连接的优点是一旦找到匹配项就应该“停止查找”。

在交易日期加入似乎是多余的,但两种方式都可以尝试。

【讨论】:

    【解决方案2】:

    你可以试试窗口函数:

    SELECT t.id, t.object, t.date
    FROM (SELECT t.*,
                 SUM(CASE WHEN t.object = 'B' THEN 1 ELSE 0 END) OVER (PARTITION BY t.id, t.transaction_date) as cnt
          FROM BigTable t
          WHERE t.transaction_date = DATE '2018-10-01'
         ) t
    WHERE cnt > 0;
    

    一种可能是您误解了分区,并且查询中正在读取表的全部内容。

    【讨论】:

      【解决方案3】:

      在将日期字符串与日期进行比较时,应避免直接使用日期字符串。隐式转换的原因可能并不总是使用日期可用的分区。 Data type conversion 的文档指出

      隐式转换的算法可能会随时间变化 软件版本和 Oracle 产品之间。显式行为 转化次数更具可预测性。

      如果在索引表达式中发生隐式数据类型转换,则 Oracle 数据库可能不使用索引,因为它是为 转换前数据类型。这可能会对 性能。

      因此,最好使用 ANSI 标准日期文字

      SELECT t2.id,t2.object, t2.date
      FROM BigTable T1
      join BigTable T2 on t2.id = t1.id
         AND t2.transaction_date = DATE '2018-10-01'
         AND t2.object = 'B'
      where t1.date = DATE '2018-10-01'
      

      另外,正如 cmets 中已经建议的那样,在 (date, id, transaction_date, object) 上创建一个 LOCAL INDEX,以进一步提高使用索引和分区修剪的扫描速度。

      【讨论】:

        猜你喜欢
        • 2012-01-16
        • 1970-01-01
        • 2020-06-06
        • 1970-01-01
        • 1970-01-01
        • 2017-02-22
        • 2018-05-22
        • 1970-01-01
        • 2012-12-22
        相关资源
        最近更新 更多