На что можно заменить временную таблицу?!

UDjihn
Дата: 07.12.2012 14:13:36
Имеется: 3 связанных таблицы. Их сцепка выглядела примерно так:
select /*+ rule */
TRUNC(c1.C_DATE_PROC),
a1.ID SALLARYID,
c1.C_DEPOSIT DEPTREATYID,
c1.C_SUMMA AMOUNT
from c1, b1, a1
where b1.C_ID = a1.C_ID and b1.STATE_ID = 'PROCESSED'
and c1.ID = b1.ID
and TRUNC(c1.C_DATE_PROC) >= P_DATE_BEG between P_DATE_END
and c1.STATE_ID = 'PROCESSED' and NVL(c1.C_SUMMA,0) != 0;
Все поля типа ID индексированы. Создавать новые индексы или менять старые нельзя.
Вся эта прелесть выполняется в районе 2.5 часов для 1го дня, что не есть комильфо. Единственное удобоваримое решение которое я смог найти, стало выборка таблицы b1 по условию b1.STATE_ID = 'PROCESSED' во временную таблицу индексация ее по 2м полям, а затем подстановка ее в выборку.
Теперь проблема: как выяснилось, создать временную таблицу в рабочей базе я не могу.
Чем можно заменить проиндексированную временную таблицу?
Изя Кацман
Дата: 07.12.2012 14:17:37
UDjihn
Имеется: 3 связанных таблицы. Их сцепка выглядела примерно так:
 select /*+ rule */  
       TRUNC(c1.C_DATE_PROC), 
       a1.ID SALLARYID, 
       c1.C_DEPOSIT DEPTREATYID, 
       c1.C_SUMMA AMOUNT
 from c1, b1, a1
 where b1.C_ID = a1.C_ID  and b1.STATE_ID = 'PROCESSED' 
          and c1.ID = b1.ID 
          and TRUNC(c1.C_DATE_PROC) >= P_DATE_BEG between P_DATE_END 
          and c1.STATE_ID = 'PROCESSED' and NVL(c1.C_SUMMA,0) != 0;

Все поля типа ID индексированы. Создавать новые индексы или менять старые нельзя.
Вся эта прелесть выполняется в районе 2.5 часов для 1го дня, что не есть комильфо. Единственное удобоваримое решение которое я смог найти, стало выборка таблицы b1 по условию b1.STATE_ID = 'PROCESSED' во временную таблицу индексация ее по 2м полям, а затем подстановка ее в выборку.
Теперь проблема: как выяснилось, создать временную таблицу в рабочей базе я не могу.
Чем можно заменить проиндексированную временную таблицу?
comphead
Дата: 07.12.2012 14:19:15
UDjihn
Имеется: 3 связанных таблицы. Их сцепка выглядела примерно так:
select /*+ rule */
TRUNC(c1.C_DATE_PROC),
a1.ID SALLARYID,
c1.C_DEPOSIT DEPTREATYID,
c1.C_SUMMA AMOUNT
from c1, b1, a1
where b1.C_ID = a1.C_ID and b1.STATE_ID = 'PROCESSED'
and c1.ID = b1.ID
and TRUNC(c1.C_DATE_PROC) >= P_DATE_BEG between P_DATE_END
and c1.STATE_ID = 'PROCESSED' and NVL(c1.C_SUMMA,0) != 0;
Все поля типа ID индексированы. Создавать новые индексы или менять старые нельзя.
Вся эта прелесть выполняется в районе 2.5 часов для 1го дня, что не есть комильфо. Единственное удобоваримое решение которое я смог найти, стало выборка таблицы b1 по условию b1.STATE_ID = 'PROCESSED' во временную таблицу индексация ее по 2м полям, а затем подстановка ее в выборку.
Теперь проблема: как выяснилось, создать временную таблицу в рабочей базе я не могу.
Чем можно заменить проиндексированную временную таблицу?



может стоит разобраться чего оно так долго?

зачем использован хинт RULE?
стастистика?
планы без хинта?
Изя Кацман
Дата: 07.12.2012 14:20:54
UDjihn
Теперь проблема: как выяснилось, создать временную таблицу в рабочей базе я не могу.
Чем можно заменить проиндексированную временную таблицу?

- Попроси создать её того, кто может
- Напиши бумагу начальству, где ты опишешь размер счастья,
от которого счастливые пользователи станут еще счастливее,
если ты создашь такую таблицу
UDjihn
Дата: 07.12.2012 14:36:08
Создать таблицу просто нереально. Чужой продукт.
Почему так медленно:
SELECT STATEMENT, GOAL = ALL_ROWS 24715 8835 1067808540 715635 24456
FILTER
NESTED LOOPS
NESTED LOOPS 24715 8835 1067808540 715635 24456
!!! NESTED LOOPS 24096 8835 1062340551 574275 23837
!!! TABLE ACCESS FULL b1 2753 75686 443649331 2043522 2645
TABLE ACCESS BY INDEX ROWID c1 1 1 8174 38 1
INDEX RANGE SCAN IDX_b1_COL_ID 1 39 1045 1
INDEX RANGE SCAN IDX_c1_id 1 1 74 1
TABLE ACCESS BY INDEX ROWID a1 1 1 619 16 1
orawish
Дата: 07.12.2012 14:53:16
UDjihn,

trunc то нафига нужен, если всё равно дальше тоё в between суёте?

ну и это - не живой код
and TRUNC(c1.C_DATE_PROC) >= P_DATE_BEG between P_DATE_END
and c1.STATE_ID = 'PROCESSED' and NVL(c1.C_SUMMA,0) != 0;
ASpens
Дата: 07.12.2012 15:13:24
UDjihn
Создать таблицу просто нереально. Чужой продукт.
SELECT STATEMENT, GOAL = ALL_ROWS              24715 8835  1067808540 715635  24456
 FILTER							
  NESTED LOOPS							
   NESTED LOOPS                                24715 8835  1067808540 715635  24456
 !!!   NESTED LOOPS                            24096 8835  1062340551 574275  23837
 !!!   TABLE ACCESS FULL         b1            2753  75686 443649331  2043522 2645
     TABLE ACCESS BY INDEX ROWID c1            1     1     8174       38      1
      INDEX RANGE SCAN	         IDX_b1_COL_ID       1     39         1045    1
    INDEX RANGE SCAN             IDX_c1_id           1     1          74      1
   TABLE ACCESS BY INDEX ROWID   a1            1     1     619        16      1


Попробую снова намекнуть, что вывод стоит форматировать а не просто copy-paste, если рассчитываете получить ответ.

UDjihn
Почему так медленно:

в b1 есть индекс по полю C_ID? статистика по нему актуальная? Его селективность?
Wool
Дата: 07.12.2012 15:53:06
Можно
1. выкинуть условие b1.STATE_ID = 'PROCESSED'
оно избыточно, т.к. есть с1.STATE_ID = 'PROCESSED'
2. избавиться наоборот, от условия с1.STATE_ID = 'PROCESSED'
user1251
Дата: 07.12.2012 16:11:32
select TRUNC(c1.C_DATE_PROC),
       a1.ID SALLARYID,
       c1.C_DEPOSIT DEPTREATYID,
       c1.C_SUMMA AMOUNT
  from c1, b1, a1
 where b1.C_ID = a1.C_ID
   and b1.STATE_ID = 'PROCESSED'
   and c1.ID = b1.ID
   and TRUNC(c1.C_DATE_PROC) >= P_DATE_BEG between P_DATE_END and
       c1.STATE_ID = 'PROCESSED'
   and NVL(c1.C_SUMMA, 0) != 0;


SELECT STATEMENT, GOAL = ALL_ROWS              24715 8835  1067808540 715635  24456
 FILTER							
  NESTED LOOPS							
   NESTED LOOPS                                24715 8835  1067808540 715635  24456
    NESTED LOOPS                            24096 8835  1062340551 574275  23837
     TABLE ACCESS FULL         b1            2753  75686 443649331  2043522 2645
     TABLE ACCESS BY INDEX ROWID c1            1     1     8174       38      1
      INDEX RANGE SCAN	         IDX_b1_COL_ID       1     39         1045    1
    INDEX RANGE SCAN             IDX_c1_id           1     1          74      1
   TABLE ACCESS BY INDEX ROWID   a1            1     1     619        16      1

1. Так будет еще лучше, а выводить планы нужно минимум с filter predicates

2. Привидите не кастрированный
         and TRUNC(c1.C_DATE_PROC) >= P_DATE_BEG between P_DATE_END 


3. Посмотрите, правильная ли статистика

4. Проблема, имхо, с индексом на b1.ID, проверьте его, что-то с ним не так, попробуйте хинт

/*+ index(b1 имя_индекса) */
user1251
Дата: 07.12.2012 16:20:43
Да, и еще, сколько строк возвращает SQL запрос реально?