Oracle группа слишком долго - PullRequest
1 голос
/ 07 июля 2011

У меня есть этот запрос:

  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

Я добавил все столбцы в «group by», и это работает.

Этот запрос работает только с "rownum". Когда я пытаюсь удалить "rownum" - приближающиеся данные слишком длинные ... более 50 минут ..

Как мне переписать sql без использования rowcount?
Спасибо.

Данные аппроксимации в таблице превышают 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
)

Ответы [ 3 ]

3 голосов
/ 07 июля 2011

Мало того, что у вас есть декартово произведение между 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 <= 10, быстро возвращается, но удаление его вызывает проблему с производительностью, говорит мне, что он либо пытается вернуть огромное количество записей (декартово произведение), либо в вашем плане выполнения есть некоторые серьезные проблемы, возможно, сканирование полной таблицы (или большого диапазона индексов) больших таблиц. </p>

В любом случае, лучший способ проверить это, если вы не можете сгенерировать план объяснения, - это временно удалить таблицу BILL_HISTROY из вашего запроса, чтобы проверить, не повышается ли производительность, если вы обнаружили проблему.

Разберитесь в соединении между этими двумя таблицами, и это определенно поможет. Получите нам план объяснения, и мы сможем дать вам более четкий ответ.

2 голосов
/ 07 июля 2011

Без плана объяснения сложно сказать наверняка, но я думаю, что проблема связана с этим:

FROM latrep.ADDRESSES adres ,
     BILL_HISTORY B

У вас там декартово произведение. Без условия соединения он объединит каждую строку в АДРЕСАХ с каждой строкой в ​​BILL_HISTORY поверх всех остальных объединений. Это заставит это принять вечность. Позже вы получите это, чтобы попытаться сузить его, но я подозреваю, что операционная система заставляет его выполнить полное сканирование таблицы и декартово произведение, прежде чем оно сможет соответствовать любому из критериев:

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

Попробуйте полностью извлечь BILL_HISTORY из запроса и посмотреть, значительно ли улучшится производительность. Если это так, то, вероятно, в этом ваша проблема. (А затем обратитесь к своему администратору базы данных, чтобы получить EXPLAIN PLAN, действительно необходимо решить подобные проблемы.)

1 голос
/ 07 июля 2011

Я думаю, что есть забытое условие для присоединения

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