【问题标题】:Oracle group by too long timeOracle 分组时间过长
【发布时间】:2011-09-30 08:37:23
【问题描述】:

我有这个查询:

  SELECT B.BILL_BALANCE,
       B.PRIME_UID,
       home.IDENT,
       PRESENT.ACC_LOGIN,
       PRESENT.ACCOUNT_NAME2,
       eq .ACCESS_NO AS PHONE,
           adres.DISP_STREET_NAME,
           B.BILL_DT
FROM addresses adres ,
     BILL_HISTORY B
LEFT JOIN eq eq ON eq.ACCOUNT_NO = B.ACCOUNT_NO
JOIN sec PRESENT ON B.ACCOUNT_NO = PRESENT.ACCOUNT_NO
JOIN sec_text home ON home.ACCOUNT_NO = B.ACCOUNT_NO
WHERE eq.STATUS_CD = 'CU'
  AND (B.BILL_TP_CD='CB'
       OR B.BILL_TP_CD='FB')
  AND (PRESENT.bill_addr_UID=adres.PRIME_UID
       OR PRESENT.COMPANY_REG_ADDR_UID=adres.PRIME_UID)
  AND B.BILL_PAID_DT IS NULL
  AND B.BILL_DT >= to_date('2011-07-01')
  AND B.BILL_DT <= to_date('2011-07-02')
  AND rownum <=1000
GROUP BY B.PRIME_UID,
         B.BILL_BALANCE,
         home.IDENT,
         PRESENT.ACC_LOGIN,
         PRESENT.ACCOUNT_NAME2,
         eq .ACCESS_NO,
             adres.DISP_STREET_NAME,
             B.BILL_DT

我需要按 B.PRIME_UID 进行“分组”,之后我遇到了这个错误:

    [code] => 979
    [message] => ORA-00979: not a GROUP BY expression
    [offset] => 8

我将所有列添加到“分组依据”并且它有效。

此查询仅适用于“rownum”。当我尝试删除“rownum”时 - 接近数据太长..超过 50 分钟..

如何在不使用 rowcount 的情况下重写 sql?
谢谢。

表格中的近似数据超过100 000。

更新*
“解释计划”不起作用。

Array
(
    [error] => 1
    [error text] => not found
    [sql] => EXPLAIN PLAN FOR
SELECT  B.BILL_BALANCE,B.PRIME_UID,home.IDENT,PRESENT.ACC_LOGIN,PRESENT.ACCOUNT_NAME2,eq .ACCESS_NO as PHONE,adres.DISP_STREET_NAME,B.BILL_DT
FROM addresses adres ,BILL_HISTORY B 
     LEFT JOIN eq eq ON eq.ACCOUNT_NO = B.ACCOUNT_NO 
     JOIN   sec PRESENT
         ON B.ACCOUNT_NO = PRESENT.ACCOUNT_NO
     JOIN sec_text home
         ON home.ACCOUNT_NO = B.ACCOUNT_NO



WHERE  
eq.STATUS_CD = 'CU'  AND
 (B.BILL_TP_CD='CB' OR B.BILL_TP_CD='FB') 
AND  (PRESENT.bill_addr_UID=adres.PRIME_UID OR PRESENT.COMPANY_REG_ADDR_UID=adres.PRIME_UID) 
AND B.BILL_PAID_DT IS NULL 
 AND B.BILL_DT >= to_date('2011-07-01') 
 AND B.BILL_DT <= to_date('2011-07-02') 

AND rownum <=10
GROUP BY B.PRIME_UID,B.BILL_BALANCE,home.IDENT,PRESENT.ACC_LOGIN,PRESENT.ACCOUNT_NAME2,eq .ACCESS_NO,adres.DISP_STREET_NAME,B.BILL_DT
)

【问题讨论】:

  • 您预计的执行计划是什么样的?把EXPLAIN PLAN FOR放在你的SQL语句前面。
  • 我更新了我的问题。“解释计划”不起作用。
  • 与您的 DBA 讨论将 EXPLAIN PLAN 表添加到您的模式,该错误与没有计划表有关。此外,他们还应该能够帮助您完成计划,因此您可以了解从哪里开始查找查询中的问题。

标签: sql oracle group-by ora-00979


【解决方案1】:

您不仅在 latrep.ADDRESSES 和 BILL_HISTORY 之间有一个笛卡尔积,这很可能会降低查询的性能,而且您还忽略了为 TO_DATE 函数指定日期格式 而不是:AND B.BILL_DT >= to_date('2011-07-01')

使用:AND B.BILL_DT >= to_date('2011-07-01', 'YYYY-MM-DD')

通过指定 rownum

无论哪种方式,如果您无法生成解释计划,最好的测试方法是暂时从您的查询中删除表 BILL_HISTROY 以查看性能是否提高,如果是这样,您已经确定了问题。

理清这两个表之间的连接,它肯定会有所帮助。给我们一个解释计划,我们可以给你一个更明确的答案。

【讨论】:

    【解决方案2】:

    没有解释计划很难确定,但我认为问题与此有关:

    FROM latrep.ADDRESSES adres ,
         BILL_HISTORY B
    

    那里有一个笛卡尔积。在没有连接条件的情况下,它将 ADDRESSES 中的每一行连接到 BILL_HISTORY 中的每一行,在所有其他连接之上。这将使它成为永恒。您稍后会尝试缩小范围,但我怀疑 OR 导致它必须执行全表扫描和笛卡尔积才能匹配任何条件:

      AND (SUB.bill_addr_UID=adres.PRIME_UID
           OR SUB.COMPANY_REG_ADDR_UID=adres.PRIME_UID)
    

    尝试将 BILL_HISTORY 完全从查询中提取出来,看看性能是否有显着提高。如果是这样,那可能就是您的问题所在。 (然后去找你的 DBA 让 EXPLAIN PLAN 发挥作用,解决这样的问题真的很有必要。)

    【讨论】:

    • 感谢您的评论,这对我来说是必要的。
    • @Oyeme - 我明白这一点,但您可以将其删除以进行测试吗?如果通过删除一个表来显着加快查询速度,那么这就是您的问题所在,我们知道在哪里修复它。 :)
    【解决方案3】:

    我觉得有一个忘记加入的条件

    latrep.ADDRESSES adres 
    

    BILL_HISTORY B
    

    这就是为什么它需要这么长时间。

    而且您只能在您的 select 子句(查询的一部分)中直接拥有 group by 子句中的内容。如果您不想/不需要按其他列分组,则不应将它们放在那里。您应该酌情使用 max、min、avg、... 作为它们的值的聚合函数。

    例如

    select date_in, 
           min(id) as ids_from, 
           max(id) as ids_to
      from table
     group by date_in;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-04-05
      • 1970-01-01
      • 2014-10-09
      • 1970-01-01
      • 2016-09-21
      • 1970-01-01
      • 2021-10-16
      • 2016-07-19
      相关资源
      最近更新 更多