powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Подскажите, как правильно составить запрос, чтобы эффективно использовались индексы
25 сообщений из 60, страница 2 из 3
Подскажите, как правильно составить запрос, чтобы эффективно использовались индексы
    #39325467
nimad
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Alibek B.,

В индексе
Код: plsql
1.
UPPER("VALUE")


В запросе
Код: plsql
1.
CA.VALUE like :address
...
Рейтинг: 0 / 0
Подскажите, как правильно составить запрос, чтобы эффективно использовались индексы
    #39325508
Alibek B
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SYЕсли таблице дан элиас то в хинте необходимо указывать его а не имя таблицы:
Исправил.

nimadВ индексе
Код: plsql
1.
UPPER("VALUE")



Я почему-то считал, что like регистронезависимый.
Исправил, указал upper(CA.VALUE) like upper(:address).

План поменялся:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
-----------------------------------------------------------------------------------------------------------------------------
| Id  | Operation                                | Name                     | Rows  | Bytes |TempSpc| Cost (%CPU)| Time     |
-----------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                         |                          |  2381 |  1216K|       |   601M  (1)|999:59:59 |
|   1 |  HASH GROUP BY                           |                          |  2381 |  1216K|  2552K|   601M  (1)|999:59:59 |
|*  2 |   FILTER                                 |                          |       |       |       |            |          |
|*  3 |    HASH JOIN RIGHT OUTER                 |                          |  2381 |  1216K|       |   601M  (1)|999:59:59 |
|*  4 |     TABLE ACCESS FULL                    | BM_CUSTOMER_CONTACT      |  5951 |   249K|       |   194   (1)| 00:00:03 |
|   5 |     NESTED LOOPS                         |                          |  2381 |  1116K|       |   601M  (1)|999:59:59 |
|*  6 |      HASH JOIN                           |                          |  2381 |  1078K|       |   601M  (1)|999:59:59 |
|   7 |       TABLE ACCESS FULL                  | BM_CUSTOMER_TYPE         |     9 |   351 |       |     3   (0)| 00:00:01 |
|*  8 |       HASH JOIN                          |                          |  2381 |   988K|       |   601M  (1)|999:59:59 |
|*  9 |        TABLE ACCESS FULL                 | BM_CUSTOMER_CONTACT      |  7044 |   295K|       |   194   (1)| 00:00:03 |
|* 10 |        HASH JOIN                         |                          |  3128 |  1166K|       |   601M  (1)|999:59:59 |
|* 11 |         INDEX RANGE SCAN                 | IDGROUPS_PK              |     4 |    72 |       |     2   (0)| 00:00:01 |
|* 12 |         HASH JOIN                        |                          | 55261 |    19M|       |   601M  (1)|999:59:59 |
|  13 |          TABLE ACCESS BY INDEX ROWID     | BM_CUSTOMER_CONTACT      |   310 | 13330 |       |    46   (0)| 00:00:01 |
|* 14 |           INDEX RANGE SCAN               | CUSTOMER_CONTACT_VAL_IDX |    56 |       |       |     3   (0)| 00:00:01 |
|* 15 |          HASH JOIN                       |                          |  1711K|   523M|       |   601M  (1)|999:59:59 |
|* 16 |           TABLE ACCESS FULL              | CUSTOMERS                |  9607 |   262K|       |    14   (0)| 00:00:01 |
|* 17 |           HASH JOIN RIGHT OUTER          |                          |  1841K|   514M|       |   601M  (1)|999:59:59 |
|* 18 |            TABLE ACCESS FULL             | RADREPLY                 |   179 | 11098 |       |   417   (1)| 00:00:06 |
|* 19 |            HASH JOIN                     |                          |  1841K|   405M|  2432K|   601M  (1)|999:59:59 |
|  20 |             TABLE ACCESS FULL            | SERVICES                 | 47769 |  1865K|       |   194   (1)| 00:00:03 |
|  21 |             NESTED LOOPS                 |                          |  1841K|   335M|       |   601M  (1)|999:59:59 |
|  22 |              NESTED LOOPS                |                          |   283M|  6757M|       |    33M  (1)|113:03:10 |
|* 23 |               TABLE ACCESS FULL          | SERVICES                 | 23691 |   208K|       |   194   (1)| 00:00:03 |
|* 24 |               TABLE ACCESS BY INDEX ROWID| BM_SERVICE_MONEY         | 11964 |   186K|       | 13773   (1)| 00:02:46 |
|* 25 |                INDEX RANGE SCAN          | SVRM_SERVICE_IDX         | 71759 |       |       |   319   (1)| 00:00:04 |
|* 26 |              TABLE ACCESS BY INDEX ROWID | RADACCT                  |     1 |   166 |       |     2   (0)| 00:00:01 |
|* 27 |               INDEX UNIQUE SCAN          | RADACCT_PK               |     1 |       |       |     1   (0)| 00:00:01 |
|* 28 |      INDEX UNIQUE SCAN                   | GROUP_PK                 |     1 |    16 |       |     0   (0)| 00:00:01 |
-----------------------------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

2 - filter(TO_DATE(:PERIOD_BEG,'yyyy-mm-dd hh24:mi:ss')<=TO_DATE(:PERIOD_END,'yyyy-mm-dd hh24:mi:ss'))
3 - access("CP"."CUSTOMER_ID"(+)="C"."CUSTOMER_ID")
4 - filter("CP"."CONTACT_DICT_ID"(+)=6)
6 - access("CT"."CUSTOMER_TYPE_ID"="C"."CUSTOMER_TYPE_ID")
8 - access("CC"."CUSTOMER_ID"="C"."CUSTOMER_ID")
9 - filter("CC"."CONTACT_DICT_ID"=100)
10 - access("C"."GROUP_ID"="ID")
11 - access("SCOPE"='client-groups-sms')
12 - access("CA"."CUSTOMER_ID"="C"."CUSTOMER_ID")
14 - access("CA"."CONTACT_DICT_ID"=3 AND UPPER("VALUE") LIKE UPPER(:ADDRESS)) filter(UPPER("VALUE") LIKE UPPER(:ADDRESS))
15 - access("C"."CUSTOMER_ID"="S"."CUSTOMER_ID")
16 - filter("C"."STATUS">0)
17 - access("SR"."SERVICE_ID"(+)="S"."SERVICE_ID")
18 - filter("SR"."ATTRIBUTE"(+)='Framed-IP-Address' AND "SR"."DATE_END"(+) IS NULL AND "SR"."DATE_BEG"(+)<=SYSDATE@!)
19 - access("S"."SERVICE_ID"="S"."SERVICE_ID")
23 - filter("S"."TYPE_ID"=14)
24 - filter("B"."TARIFFEL_ID" IS NOT NULL)
25 - access("S"."SERVICE_ID"="B"."SERVICE_ID")
26 - filter("R"."ACCTSTARTTIME">=TO_DATE(:PERIOD_BEG,'yyyy-mm-dd hh24:mi:ss') AND "R"."ACCTSTARTTIME"<=TO_DATE(:PERIOD_END,'yyyy-mm-dd hh24:mi:ss'))
27 - access("B"."RADACCTID"="R"."RADACCTID")
28 - access("CG"."GROUP_ID"="C"."GROUP_ID")

Даже INDEX RANGE SCAN для CUSTOMER_CONTACT_VAL_IDX появился.
Но запрос по прежнему отрабатывает очень долго.

Сейчас поэкспериментирую, мне кажется, что дальше я уже разберусь.
...
Рейтинг: 0 / 0
Подскажите, как правильно составить запрос, чтобы эффективно использовались индексы
    #39325572
Alibek B
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SYЕсли таблице дан элиас то в хинте необходимо указывать его а не имя таблицы:
Странно, стало намного хуже.
Без хинтов запрос выполняется полторы минуты, с хинтами за полчаса не завершился.
Оставил только USE_NL(S B R T), он вроде бы дает положительный эффект.
А LEADING и INDEX убрал.
В LEADING определяется порядок соединений и по идее LEADING(S B R) должен помогать, но видимо я неправильно понимаю идею.
...
Рейтинг: 0 / 0
Подскажите, как правильно составить запрос, чтобы эффективно использовались индексы
    #39325729
Alibek B
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Чем дальше, тем меньше понимаю.

Есть запрос, выполняемый веб-приложением (скриптом на PHP). Запрос возвращает несколько строк (не более пары десятков).
Выполняется очень долго, веб-сервер закрывает скрипт по таймауту.

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
select * from (
select
  C.CUSTOMER_ID as ID
, CT.NAME as TYPE
, CC.VALUE as CLIENT
, CP.VALUE as PHONE
, CA.VALUE as ADDRESS
, S.SERVICE_ID as SERVICE_ID
, S.LOGIN as SERVICE_LOGIN
, SR.VALUE as SERVICE_IP
, Z.CURSESSIONS_ID as SESSION_ID
, R.USERNAME as SESSION_USERNAME
, R.ACCTSESSIONID as SESSION_KEY
, R.ACCTSTARTTIME as SESSION_START
, null as SESSION_STOP
, 86400 * (sysdate - R.ACCTSTARTTIME) as SESSION_TIME
, R.ACCTINPUTOCTETS as SESSION_DL
, R.ACCTOUTPUTOCTETS as SESSION_UL
, R.ACCTTERMINATECAUSE as SESSION_TERMINATE
, R.CALLINGSTATIONID as PORT
, R.FRAMEDIPADDRESS as IP
, R.CLIENT_MAC_ADDRESS as MAC
from CUSTOMERS C
join BM_GROUP CG on (CG.GROUP_ID = C.GROUP_ID)
join BM_CUSTOMER_TYPE CT on (CT.CUSTOMER_TYPE_ID = C.CUSTOMER_TYPE_ID)
join BM_CUSTOMER_CONTACT CC on (CC.CUSTOMER_ID = C.CUSTOMER_ID and CC.CONTACT_DICT_ID = 100)
left join BM_CUSTOMER_CONTACT CP on (CP.CUSTOMER_ID = C.CUSTOMER_ID and CP.CONTACT_DICT_ID = 6)
left join BM_CUSTOMER_CONTACT CA on (CA.CUSTOMER_ID = C.CUSTOMER_ID and CA.CONTACT_DICT_ID = 3)
join SERVICES S on (S.CUSTOMER_ID = C.CUSTOMER_ID and S.TYPE_ID = 14 and S.STATUS != -20 and not exists (select TARIFFEL_ID from BM_TARIFFEL where TARIFF_ID = S.TARIFF_ID and TARIFFEL_TYPE_ID = 908))
left join RADREPLY SR on (SR.SERVICE_ID = S.SERVICE_ID and SR.ATTRIBUTE = 'Framed-IP-Address' and SR.DATE_BEG <= sysdate and SR.DATE_END is null)
left join CURSESSIONS Z on (Z.SERVICE_ID = S.SERVICE_ID)
left join RADACCT R on (R.RADACCTID = Z.RADACCTID)
where C.GROUP_ID in (select ID from TEMP.IDGROUPS where SCOPE = 'client-groups-sms')
and C.STATUS > 0
and coalesce(R.FRAMEDIPADDRESS,SR.VALUE,'-') = :ip
and CA.CONTACT_DICT_ID = 3 and upper(CA.VALUE) like upper(:address)
and R.ACCTSTARTTIME >= to_date(:period_beg,'yyyy-mm-dd hh24:mi:ss')
and R.ACCTSTARTTIME <= to_date(:period_end,'yyyy-mm-dd hh24:mi:ss')
union all
select
  C.CUSTOMER_ID as ID
, CT.NAME as TYPE
, CC.VALUE as CLIENT
, CP.VALUE as PHONE
, CA.VALUE as ADDRESS
, S.SERVICE_ID as SERVICE_ID
, S.LOGIN as SERVICE_LOGIN
, SR.VALUE as SERVICE_IP
, null as SESSION_ID
, R.USERNAME as SESSION_USERNAME
, R.ACCTSESSIONID as SESSION_KEY
, R.ACCTSTARTTIME as SESSION_START
, R.ACCTSTOPTIME as SESSION_STOP
, R.ACCTSESSIONTIME as SESSION_TIME
, R.ACCTINPUTOCTETS as SESSION_DL
, R.ACCTOUTPUTOCTETS as SESSION_UL
, R.ACCTTERMINATECAUSE as SESSION_TERMINATE
, R.CALLINGSTATIONID as PORT
, R.FRAMEDIPADDRESS as IP
, R.CLIENT_MAC_ADDRESS as MAC
from (
select --/*+ USE_NL(S B R T) */
  R.RADACCTID
, S.SERVICE_ID
, R.USERNAME
, R.ACCTSESSIONID
, R.ACCTSTARTTIME
, R.ACCTSTOPTIME
, R.ACCTSESSIONTIME
, R.ACCTINPUTOCTETS
, R.ACCTOUTPUTOCTETS
, R.ACCTTERMINATECAUSE
, R.CALLINGSTATIONID
, R.FRAMEDIPADDRESS
, R.CLIENT_MAC_ADDRESS
from RADACCT R
join BM_SERVICE_MONEY B on (B.RADACCTID = R.RADACCTID)
join BM_TARIFFEL T on (T.TARIFFEL_ID = B.TARIFFEL_ID)
join SERVICES S on (S.SERVICE_ID = B.SERVICE_ID)
where S.TYPE_ID = 14
and R.ACCTSTARTTIME >= to_date(:period_beg,'yyyy-mm-dd hh24:mi:ss')
and R.ACCTSTARTTIME <= to_date(:period_end,'yyyy-mm-dd hh24:mi:ss')
group by
  R.RADACCTID
, S.SERVICE_ID
, R.USERNAME
, R.ACCTSESSIONID
, R.ACCTSTARTTIME
, R.ACCTSTOPTIME
, R.ACCTSESSIONTIME
, R.ACCTINPUTOCTETS
, R.ACCTOUTPUTOCTETS
, R.ACCTTERMINATECAUSE
, R.CALLINGSTATIONID
, R.FRAMEDIPADDRESS
, R.CLIENT_MAC_ADDRESS
) R
join SERVICES S on (S.SERVICE_ID = R.SERVICE_ID)
join CUSTOMERS C on (C.CUSTOMER_ID = S.CUSTOMER_ID)
join BM_GROUP CG on (CG.GROUP_ID = C.GROUP_ID)
join BM_CUSTOMER_TYPE CT on (CT.CUSTOMER_TYPE_ID = C.CUSTOMER_TYPE_ID)
join BM_CUSTOMER_CONTACT CC on (CC.CUSTOMER_ID = C.CUSTOMER_ID and CC.CONTACT_DICT_ID = 100)
left join BM_CUSTOMER_CONTACT CP on (CP.CUSTOMER_ID = C.CUSTOMER_ID and CP.CONTACT_DICT_ID = 6)
left join BM_CUSTOMER_CONTACT CA on (CA.CUSTOMER_ID = C.CUSTOMER_ID and CA.CONTACT_DICT_ID = 3)
left join RADREPLY SR on (SR.SERVICE_ID = S.SERVICE_ID and SR.ATTRIBUTE = 'Framed-IP-Address' and SR.DATE_BEG <= sysdate and SR.DATE_END is null)
where C.GROUP_ID in (select ID from TEMP.IDGROUPS where SCOPE = 'client-groups-sms')
and C.STATUS > 0
and R.FRAMEDIPADDRESS = :ip
and CA.CONTACT_DICT_ID = 3 and upper(CA.VALUE) like upper(:address)
)




Этот же запрос я сегодня запускал в TOAD — в первый раз он выполнялся около полутора минут, в следующие разы отрабатывал быстро (секунды), даже если я изменял некоторые параметры.

Затем я этот же запрос запустил в SQL*Plus, предварительно задав параметры (такие же как на сайте и в TOAD):
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
var ip varchar2(20)
exec :ip:='11.22.33.44'
var address varchar2(40)
exec :address:='Международная%'
var period_beg varchar2(20)
exec :period_beg:='2016-10-01 00:00:00'
var period_end varchar2(20)
exec :period_end:='9999-01-01 23:59:59'
В первый раз запрос выполнялся больше минуты, в следующие разы выполнялся за секунды.

С сайта запрос по прежнему выполнялся очень долго (точнее его прерывал сервер по таймауту).

Сейчас решил снова проверить, запустил его в SQL*Plus — и он выполняется уже почти 10 минут.

Запустил его же в TOAD, с теми же параметрами — запрос выполнился за 31 секунду.
Повторные запуски — около 400мс.

Остановил запрос в SQL*Plus (прошло более 10 минут, он так и не завершился).
Запустил его еще раз, прошло уже минуты четыре, а он так и не завершился.


Почему в TOAD запрос выполняется быстро? Даже если изменять параметры (:ip или :address), время выполнения не превышает десятка секунд.
Почему в SQL*Plus днем он выполнялся быстро, а сейчас долго? SQL*Plus один и тот же, на одной и той же машине (она же сервер СУБД), никаких настроек или окружение среды я не изменял (да и не умею).
Почему из PHP (используется библиотека OCI) запрос выполняется долго? В PHP я первоначально использовал хинт RESULT_CACHE, но я пробовал его убирать, ничего не менялось.

Вот текущий план из TOAD:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
-------------------------------------------------------------------------------------------------------------------------
| Id  | Operation                                   | Name                      | Rows  | Bytes | Cost (%CPU)| Time     |
-------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                            |                           |     2 |  3284 |   151K  (1)| 00:30:22 |
|   1 |  VIEW                                       |                           |     2 |  3284 |   151K  (1)| 00:30:22 |
|   2 |   UNION-ALL                                 |                           |       |       |            |          |
|*  3 |    FILTER                                   |                           |       |       |            |          |
|   4 |     NESTED LOOPS                            |                           |     1 |   437 |   202   (2)| 00:00:03 |
|   5 |      NESTED LOOPS                           |                           |     3 |   852 |   196   (2)| 00:00:03 |
|   6 |       NESTED LOOPS OUTER                    |                           |     4 |  1012 |   188   (2)| 00:00:03 |
|   7 |        NESTED LOOPS OUTER                   |                           |     4 |   888 |   180   (2)| 00:00:03 |
|   8 |         NESTED LOOPS                        |                           |     4 |   648 |   172   (2)| 00:00:03 |
|*  9 |          HASH JOIN ANTI                     |                           |     4 |   580 |   167   (2)| 00:00:03 |
|* 10 |           TABLE ACCESS BY INDEX ROWID       | SERVICES                  |     2 |    82 |     7   (0)| 00:00:01 |
|  11 |            NESTED LOOPS                     |                           |    35 |  4760 |   155   (2)| 00:00:02 |
|* 12 |             HASH JOIN                       |                           |    18 |  1710 |    66   (5)| 00:00:01 |
|  13 |              TABLE ACCESS BY INDEX ROWID    | BM_CUSTOMER_CONTACT       |   310 |  9610 |    46   (0)| 00:00:01 |
|* 14 |               INDEX RANGE SCAN              | CUSTOMER_CONTACT_VAL_IDX  |    56 |       |     3   (0)| 00:00:01 |
|  15 |              NESTED LOOPS                   |                           |   544 | 34816 |    19  (11)| 00:00:01 |
|* 16 |               HASH JOIN                     |                           |  9607 |   431K|    18   (6)| 00:00:01 |
|  17 |                TABLE ACCESS FULL            | BM_CUSTOMER_TYPE          |     9 |   270 |     3   (0)| 00:00:01 |
|* 18 |                TABLE ACCESS FULL            | CUSTOMERS                 |  9607 |   150K|    14   (0)| 00:00:01 |
|* 19 |               INDEX UNIQUE SCAN             | IDGROUPS_PK               |     1 |    18 |     0   (0)| 00:00:01 |
|* 20 |             INDEX RANGE SCAN                | SERV_CUSTOMER_IDX         |     7 |       |     1   (0)| 00:00:01 |
|  21 |           TABLE ACCESS BY INDEX ROWID       | BM_TARIFFEL               |   254 |  2286 |    12   (0)| 00:00:01 |
|* 22 |            INDEX RANGE SCAN                 | TAREL_TYPE_IDX            |   254 |       |     1   (0)| 00:00:01 |
|  23 |          TABLE ACCESS BY INDEX ROWID        | CURSESSIONS               |     1 |    17 |     2   (0)| 00:00:01 |
|* 24 |           INDEX RANGE SCAN                  | CURSESS_SERVICE_IDX       |     1 |       |     1   (0)| 00:00:01 |
|* 25 |         TABLE ACCESS BY INDEX ROWID         | RADREPLY                  |     1 |    60 |     3   (0)| 00:00:01 |
|* 26 |          INDEX RANGE SCAN                   | RADREPLY_SERVICE_IDX      |     8 |       |     1   (0)| 00:00:01 |
|  27 |        TABLE ACCESS BY INDEX ROWID          | BM_CUSTOMER_CONTACT       |     1 |    31 |     2   (0)| 00:00:01 |
|* 28 |         INDEX RANGE SCAN                    | CUSTOMER_CONTACT_IDX      |     1 |       |     1   (0)| 00:00:01 |
|  29 |       TABLE ACCESS BY INDEX ROWID           | BM_CUSTOMER_CONTACT       |     1 |    31 |     2   (0)| 00:00:01 |
|* 30 |        INDEX RANGE SCAN                     | CUSTOMER_CONTACT_IDX      |     1 |       |     1   (0)| 00:00:01 |
|* 31 |      TABLE ACCESS BY INDEX ROWID            | RADACCT                   |     1 |   153 |     2   (0)| 00:00:01 |
|* 32 |       INDEX UNIQUE SCAN                     | RADACCT_PK                |     1 |       |     1   (0)| 00:00:01 |
|  33 |    HASH GROUP BY                            |                           |     1 |   524 |   151K  (1)| 00:30:19 |
|* 34 |     FILTER                                  |                           |       |       |            |          |
|  35 |      NESTED LOOPS OUTER                     |                           |     1 |   524 |   151K  (1)| 00:30:19 |
|  36 |       NESTED LOOPS                          |                           |     1 |   462 |   151K  (1)| 00:30:19 |
|  37 |        NESTED LOOPS                         |                           |     1 |   446 |   151K  (1)| 00:30:19 |
|  38 |         NESTED LOOPS                        |                           |     1 |   407 |   151K  (1)| 00:30:19 |
|  39 |          NESTED LOOPS OUTER                 |                           |     1 |   364 |   151K  (1)| 00:30:19 |
|* 40 |           HASH JOIN                         |                           |     1 |   321 |   151K  (1)| 00:30:19 |
|  41 |            NESTED LOOPS                     |                           |    38 | 10564 |   151K  (1)| 00:30:19 |
|* 42 |             HASH JOIN                       |                           |   665 |   168K|   151K  (1)| 00:30:19 |
|* 43 |              HASH JOIN                      |                           |   665 |   150K|   151K  (1)| 00:30:19 |
|* 44 |               HASH JOIN                     |                           |   663 |   123K|   151K  (1)| 00:30:16 |
|* 45 |                TABLE ACCESS BY INDEX ROWID  | BM_SERVICE_MONEY          |    14 |   224 |     6   (0)| 00:00:01 |
|  46 |                 NESTED LOOPS                |                           |   662 |   117K|   151K  (1)| 00:30:14 |
|* 47 |                  TABLE ACCESS BY INDEX ROWID| RADACCT                   |    47 |  7802 |   150K  (1)| 00:30:12 |
|* 48 |                   INDEX RANGE SCAN          | RADACCT_ACCTSTARTTIME_IDX |   236K|       |  1191   (1)| 00:00:15 |
|* 49 |                  INDEX RANGE SCAN           | SVRM_RADACCT_IDX          |    14 |       |     3   (0)| 00:00:01 |
|* 50 |                TABLE ACCESS FULL            | SERVICES                  | 23960 |   210K|   194   (1)| 00:00:03 |
|  51 |               TABLE ACCESS FULL             | SERVICES                  | 47772 |  1912K|   194   (1)| 00:00:03 |
|* 52 |              TABLE ACCESS FULL              | CUSTOMERS                 |  9607 |   262K|    14   (0)| 00:00:01 |
|* 53 |             INDEX UNIQUE SCAN               | IDGROUPS_PK               |     1 |    18 |     0   (0)| 00:00:01 |
|  54 |            TABLE ACCESS BY INDEX ROWID      | BM_CUSTOMER_CONTACT       |   310 | 13330 |    46   (0)| 00:00:01 |
|* 55 |             INDEX RANGE SCAN                | CUSTOMER_CONTACT_VAL_IDX  |    56 |       |     3   (0)| 00:00:01 |
|  56 |           TABLE ACCESS BY INDEX ROWID       | BM_CUSTOMER_CONTACT       |     1 |    43 |     2   (0)| 00:00:01 |
|* 57 |            INDEX RANGE SCAN                 | CUSTOMER_CONTACT_IDX      |     1 |       |     1   (0)| 00:00:01 |
|  58 |          TABLE ACCESS BY INDEX ROWID        | BM_CUSTOMER_CONTACT       |     1 |    43 |     2   (0)| 00:00:01 |
|* 59 |           INDEX RANGE SCAN                  | CUSTOMER_CONTACT_IDX      |     1 |       |     1   (0)| 00:00:01 |
|  60 |         TABLE ACCESS BY INDEX ROWID         | BM_CUSTOMER_TYPE          |     1 |    39 |     1   (0)| 00:00:01 |
|* 61 |          INDEX UNIQUE SCAN                  | BM_CUSTOMER_TYPE_PK       |     1 |       |     0   (0)| 00:00:01 |
|* 62 |        INDEX UNIQUE SCAN                    | GROUP_PK                  |     1 |    16 |     0   (0)| 00:00:01 |
|* 63 |       TABLE ACCESS BY INDEX ROWID           | RADREPLY                  |     1 |    62 |     3   (0)| 00:00:01 |
|* 64 |        INDEX RANGE SCAN                     | RADREPLY_SERVICE_IDX      |     8 |       |     1   (0)| 00:00:01 |
-------------------------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

3 - filter(TO_DATE(:PERIOD_BEG,'yyyy-mm-dd hh24:mi:ss')<=TO_DATE(:PERIOD_END,'yyyy-mm-dd hh24:mi:ss'))
9 - access("TARIFF_ID"="S"."TARIFF_ID")
10 - filter("S"."TYPE_ID"=14 AND "S"."STATUS"<>(-20))
12 - access("CA"."CUSTOMER_ID"="C"."CUSTOMER_ID")
14 - access("CA"."CONTACT_DICT_ID"=3 AND UPPER("VALUE") LIKE UPPER(:ADDRESS))
filter(UPPER("VALUE") LIKE UPPER(:ADDRESS))
16 - access("CT"."CUSTOMER_TYPE_ID"="C"."CUSTOMER_TYPE_ID")
18 - filter("C"."STATUS">0)
19 - access("SCOPE"='client-groups-sms' AND "C"."GROUP_ID"="ID")
20 - access("S"."CUSTOMER_ID"="C"."CUSTOMER_ID")
22 - access("TARIFFEL_TYPE_ID"=908)
24 - access("Z"."SERVICE_ID"="S"."SERVICE_ID")
25 - filter("SR"."ATTRIBUTE"(+)='Framed-IP-Address' AND "SR"."DATE_END"(+) IS NULL AND
"SR"."DATE_BEG"(+)<=SYSDATE@!)
26 - access("SR"."SERVICE_ID"(+)="S"."SERVICE_ID")
28 - access("CP"."CUSTOMER_ID"(+)="C"."CUSTOMER_ID" AND "CP"."CONTACT_DICT_ID"(+)=6)
30 - access("CC"."CUSTOMER_ID"="C"."CUSTOMER_ID" AND "CC"."CONTACT_DICT_ID"=100)
31 - filter("R"."ACCTSTARTTIME">=TO_DATE(:PERIOD_BEG,'yyyy-mm-dd hh24:mi:ss') AND
"R"."ACCTSTARTTIME"<=TO_DATE(:PERIOD_END,'yyyy-mm-dd hh24:mi:ss') AND
COALESCE("R"."FRAMEDIPADDRESS","SR"."VALUE",'-')=:IP)
32 - access("R"."RADACCTID"="Z"."RADACCTID")
34 - filter(TO_DATE(:PERIOD_BEG,'yyyy-mm-dd hh24:mi:ss')<=TO_DATE(:PERIOD_END,'yyyy-mm-dd hh24:mi:ss'))
40 - access("CA"."CUSTOMER_ID"="C"."CUSTOMER_ID")
42 - access("C"."CUSTOMER_ID"="S"."CUSTOMER_ID")
43 - access("S"."SERVICE_ID"="S"."SERVICE_ID")
44 - access("S"."SERVICE_ID"="B"."SERVICE_ID")
45 - filter("B"."TARIFFEL_ID" IS NOT NULL)
47 - filter("R"."FRAMEDIPADDRESS"=:IP)
48 - access("R"."ACCTSTARTTIME">=TO_DATE(:PERIOD_BEG,'yyyy-mm-dd hh24:mi:ss') AND
"R"."ACCTSTARTTIME"<=TO_DATE(:PERIOD_END,'yyyy-mm-dd hh24:mi:ss'))
49 - access("B"."RADACCTID"="R"."RADACCTID")
50 - filter("S"."TYPE_ID"=14)
52 - filter("C"."STATUS">0)
53 - access("SCOPE"='client-groups-sms' AND "C"."GROUP_ID"="ID")
55 - access("CA"."CONTACT_DICT_ID"=3 AND UPPER("VALUE") LIKE UPPER(:ADDRESS))
filter(UPPER("VALUE") LIKE UPPER(:ADDRESS))
57 - access("CP"."CUSTOMER_ID"(+)="C"."CUSTOMER_ID" AND "CP"."CONTACT_DICT_ID"(+)=6)
59 - access("CC"."CUSTOMER_ID"="C"."CUSTOMER_ID" AND "CC"."CONTACT_DICT_ID"=100)
61 - access("CT"."CUSTOMER_TYPE_ID"="C"."CUSTOMER_TYPE_ID")
62 - access("CG"."GROUP_ID"="C"."GROUP_ID")
63 - filter("SR"."ATTRIBUTE"(+)='Framed-IP-Address' AND "SR"."DATE_END"(+) IS NULL AND
"SR"."DATE_BEG"(+)<=SYSDATE@!)
64 - access("SR"."SERVICE_ID"(+)="S"."SERVICE_ID")


С SQL*Plus план срисовать не смог, из-за переноса строк он совершенно нечитаем.
...
Рейтинг: 0 / 0
Подскажите, как правильно составить запрос, чтобы эффективно использовались индексы
    #39325747
Фотография SY
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Alibek B.С SQL*Plus план срисовать не смог, из-за переноса строк он совершенно нечитаем.

А что SET LINESIZE отменили?

Начни с проcтого. Просмoтри LEFT JOIN. Какой смысл в аутер джойнах типа:

Код: plsql
1.
2.
                  left join RADACCT R
                    on (R.RADACCTID = Z.RADACCTID)



Когда в WHERE стоит:

Код: plsql
1.
2.
              and R.ACCTSTARTTIME >= to_date(:period_beg,'yyyy-mm-dd hh24:mi:ss')
              and R.ACCTSTARTTIME <= to_date(:period_end,'yyyy-mm-dd hh24:mi:ss')




Или:

Код: plsql
1.
2.
                  left join BM_CUSTOMER_CONTACT CA
                    on (CA.CUSTOMER_ID = C.CUSTOMER_ID and CA.CONTACT_DICT_ID = 3)



Когда в WHERE стоит:

Код: plsql
1.
2.
              and CA.CONTACT_DICT_ID = 3
              and upper(CA.VALUE) like upper(:address)



Зачем два раза джойн с SERVICES? Почему бы не:

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
            from       (
                        select  --/*+ USE_NL(S B R T) */
                                R.RADACCTID,
--                                S.SERVICE_ID,
                                B.SERVICE_ID,
                                R.USERNAME,
                                R.ACCTSESSIONID,
                                R.ACCTSTARTTIME,
                                R.ACCTSTOPTIME,
                                R.ACCTSESSIONTIME,
                                R.ACCTINPUTOCTETS,
                                R.ACCTOUTPUTOCTETS,
                                R.ACCTTERMINATECAUSE,
                                R.CALLINGSTATIONID,
                                R.FRAMEDIPADDRESS,
                                R.CLIENT_MAC_ADDRESS
                          from       RADACCT R
                                join BM_SERVICE_MONEY B
                                  on (B.RADACCTID = R.RADACCTID)
                                join BM_TARIFFEL T
                                  on (T.TARIFFEL_ID = B.TARIFFEL_ID)
--                                join SERVICES S
--                                  on (S.SERVICE_ID = B.SERVICE_ID)
                          where S.TYPE_ID = 14
                            and R.ACCTSTARTTIME >= to_date(:period_beg,'yyyy-mm-dd hh24:mi:ss')
                            and R.ACCTSTARTTIME <= to_date(:period_end,'yyyy-mm-dd hh24:mi:ss')
                          group by R.RADACCTID,
--                                   S.SERVICE_ID,
                                   B.SERVICE_ID,
                                   R.USERNAME,
                                   R.ACCTSESSIONID,
                                   R.ACCTSTARTTIME,
                                   R.ACCTSTOPTIME,
                                   R.ACCTSESSIONTIME,
                                   R.ACCTINPUTOCTETS,
                                   R.ACCTOUTPUTOCTETS,
                                   R.ACCTTERMINATECAUSE,
                                   R.CALLINGSTATIONID,
                                   R.FRAMEDIPADDRESS,
                                   R.CLIENT_MAC_ADDRESS
                       ) R



Да и "в первый раз он выполнялся около полутора минут, в следующие разы отрабатывал быстро (секунды)" - данные поле первого выполнения остаются в buffer cache.

SY.
...
Рейтинг: 0 / 0
Подскажите, как правильно составить запрос, чтобы эффективно использовались индексы
    #39325882
Alibek B
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SYКакой смысл в аутер джойнах типа:
Код: plsql
1.
2.
                  left join RADACCT R
                    on (R.RADACCTID = Z.RADACCTID)



Это в первом запросе (до union), с ним вообще никаких проблем нет.
SQL формируется динамически и мне удобнее, когда тело запроса постоянное и я только добавляю ограничения в WHERE.
Во втором запросе (после union) от внешних соединений попробую избавиться.

SYЗачем два раза джойн с SERVICES? Почему бы не:

Смысл в SERVICES.TYPE_ID=14.
Записи в таблице RADACCT формируются только из SERVICES.TYPE_ID=14.
Но записи в таблице BM_SERVICE_MONEY могут быть для любого SERVICES.TYPE_ID.
И SERVICES.TYPE_ID!=14 гораздо больше, чем SERVICES.TYPE_ID=14.
Я таким образом хотел упростить наиболее "тяжелое" соединение самых больших таблиц RADACCT и BM_SERVICE_MONEY.
Попробую убрать внутреннее соединение с SERVICES, возможно оптимизатор Oracle лучше меня с этим разберется.

SYДа и "в первый раз он выполнялся около полутора минут, в следующие разы отрабатывал быстро (секунды)" - данные поле первого выполнения остаются в buffer cache.

Про кеширование после первого выполнения я предполагал. Возможно что и план запроса кешируется.
Но все равно мне непонятно, почему один и тот же запрос с одними и теми же входными параметрами и в одной и той же среде днем и вечером выполняется разное время.
Даже в TOAD, вчера днем повторные запросы (после первого запуска) отрабатывали 1-2 секунды, а вечером повторные запросы отрабатывали 400мс?
...
Рейтинг: 0 / 0
Подскажите, как правильно составить запрос, чтобы эффективно использовались индексы
    #39325992
Alibek B
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Убрал left join (заменил на обычный join), убрал из запроса пару таблиц.
Выполнил запрос в TOAD, запрос вернул около десятка строк, в первый раз выполнялся 600мс, в следующие разы выполнялся около 400мс.
Запустил этот же запрос в SQL*Plus, запрос выполнялся более 10 минут, затем я его прервал.
Затем попробовал запустить запрос в TOAD — и он висит уже более 5 минут.

Это может быть из-за блокировок?
Запросы из этой темы блокировок не показывают.
...
Рейтинг: 0 / 0
Подскажите, как правильно составить запрос, чтобы эффективно использовались индексы
    #39326072
Alibek B
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Всем большое спасибо за советы, вроде бы удалось добиться быстрой работы.
Второй подзапрос (после union) теперь выглядит так:
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
select * from (
select /*+ RESULT_CACHE */
  C.CUSTOMER_ID as ID
, CT.NAME as TYPE
, CC.VALUE as CLIENT
, CA.VALUE as ADDRESS
, S.SERVICE_ID as SERVICE_ID
, S.LOGIN as SERVICE_LOGIN
, null as SERVICE_IP
, null as SESSION_ID
, R.USERNAME as SESSION_USERNAME
, R.ACCTSESSIONID as SESSION_KEY
, R.ACCTSTARTTIME as SESSION_START
, R.ACCTSTOPTIME as SESSION_STOP
, R.ACCTSESSIONTIME as SESSION_TIME
, R.ACCTINPUTOCTETS as SESSION_DL
, R.ACCTOUTPUTOCTETS as SESSION_UL
, R.ACCTTERMINATECAUSE as SESSION_TERMINATE
, R.CALLINGSTATIONID as PORT
, R.FRAMEDIPADDRESS as IP
, R.CLIENT_MAC_ADDRESS as MAC
from (
select /* USE_NL(B R) */
  R.RADACCTID
, B.SERVICE_ID
, R.USERNAME
, R.ACCTSESSIONID
, R.ACCTSTARTTIME
, R.ACCTSTOPTIME
, R.ACCTSESSIONTIME
, R.ACCTINPUTOCTETS
, R.ACCTOUTPUTOCTETS
, R.ACCTTERMINATECAUSE
, R.CALLINGSTATIONID
, R.FRAMEDIPADDRESS
, R.CLIENT_MAC_ADDRESS
from RADACCT R
join BM_SERVICE_MONEY B on (B.RADACCTID = R.RADACCTID)
where B.TARIFFEL_ID is not null
and R.ACCTSTARTTIME >= to_date(:period_beg,'yyyy-mm-dd hh24:mi:ss')
and R.ACCTSTARTTIME <= to_date(:period_end,'yyyy-mm-dd hh24:mi:ss')
group by
  R.RADACCTID
, B.SERVICE_ID
, R.USERNAME
, R.ACCTSESSIONID
, R.ACCTSTARTTIME
, R.ACCTSTOPTIME
, R.ACCTSESSIONTIME
, R.ACCTINPUTOCTETS
, R.ACCTOUTPUTOCTETS
, R.ACCTTERMINATECAUSE
, R.CALLINGSTATIONID
, R.FRAMEDIPADDRESS
, R.CLIENT_MAC_ADDRESS
) R
join SERVICES S on (S.SERVICE_ID = R.SERVICE_ID)
join CUSTOMERS C on (C.CUSTOMER_ID = S.CUSTOMER_ID)
join BM_GROUP CG on (CG.GROUP_ID = C.GROUP_ID)
join BM_CUSTOMER_TYPE CT on (CT.CUSTOMER_TYPE_ID = C.CUSTOMER_TYPE_ID)
join BM_CUSTOMER_CONTACT CC on (CC.CUSTOMER_ID = C.CUSTOMER_ID and CC.CONTACT_DICT_ID = 100)
join BM_CUSTOMER_CONTACT CA on (CA.CUSTOMER_ID = C.CUSTOMER_ID and CA.CONTACT_DICT_ID = 3)
where C.GROUP_ID in (select ID from TEMP.IDGROUPS where SCOPE = 'client-groups-sms')
and C.STATUS > 0
and R.FRAMEDIPADDRESS = :ip
and CA.CONTACT_DICT_ID = 3 and upper(CA.VALUE) like upper(:address)
);


В TOAD этот запрос выполняется достаточно быстро, в SQL*Plus тоже.
План выглядит так:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
set linesize 1000;
set pagesize 0;

var  ip          varchar2(20);
var  address     varchar2(40);
var  period_beg  varchar2(20);
var  period_end  varchar2(20);

exec  :ip         := '11.22.33.44';
exec  :address    := 'Международная%';
exec  :period_beg := '2016-10-01 00:00:00';
exec  :period_end := '9999-01-01 23:59:59';

explain plan for
<мой SQL-запрос>;

select * from table(dbms_xplan.display);

------------------------------------------------------------------------------------------------------------------
| Id  | Operation                            | Name                      | Rows  | Bytes | Cost (%CPU)| Time     |
------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                     |                           |     1 |   997 |   151K  (1)| 00:30:16 |
|   1 |  TABLE ACCESS BY INDEX ROWID         | BM_CUSTOMER_CONTACT       |     1 |    31 |     2   (0)| 00:00:01 |
|   2 |   NESTED LOOPS                       |                           |     1 |   997 |   151K  (1)| 00:30:16 |
|   3 |    NESTED LOOPS                      |                           |     1 |   966 |   151K  (1)| 00:30:16 |
|*  4 |     HASH JOIN                        |                           |     1 |   936 |   151K  (1)| 00:30:16 |
|   5 |      TABLE ACCESS BY INDEX ROWID     | SERVICES                  |     5 |   145 |     7   (0)| 00:00:01 |
|   6 |       NESTED LOOPS                   |                           |    91 |  8554 |   150   (1)| 00:00:02 |
|   7 |        NESTED LOOPS                  |                           |    18 |  1170 |    61   (2)| 00:00:01 |
|*  8 |         HASH JOIN                    |                           |   310 | 14570 |    61   (2)| 00:00:01 |
|   9 |          TABLE ACCESS BY INDEX ROWID | BM_CUSTOMER_CONTACT       |   310 |  9610 |    46   (0)| 00:00:01 |
|* 10 |           INDEX RANGE SCAN           | CUSTOMER_CONTACT_VAL_IDX  |    56 |       |     3   (0)| 00:00:01 |
|* 11 |          TABLE ACCESS FULL           | CUSTOMERS                 |  9607 |   150K|    14   (0)| 00:00:01 |
|* 12 |         INDEX UNIQUE SCAN            | IDGROUPS_PK               |     1 |    18 |     0   (0)| 00:00:01 |
|* 13 |        INDEX RANGE SCAN              | SERV_CUSTOMER_IDX         |     7 |       |     1   (0)| 00:00:01 |
|  14 |      VIEW                            |                           |   662 |   544K|   151K  (1)| 00:30:14 |
|  15 |       HASH GROUP BY                  |                           |   662 |   117K|   151K  (1)| 00:30:14 |
|* 16 |        FILTER                        |                           |       |       |            |          |
|* 17 |         TABLE ACCESS BY INDEX ROWID  | BM_SERVICE_MONEY          |    14 |   224 |     6   (0)| 00:00:01 |
|  18 |          NESTED LOOPS                |                           |   662 |   117K|   151K  (1)| 00:30:14 |
|* 19 |           TABLE ACCESS BY INDEX ROWID| RADACCT                   |    47 |  7802 |   150K  (1)| 00:30:12 |
|* 20 |            INDEX RANGE SCAN          | RADACCT_ACCTSTARTTIME_IDX |   236K|       |  1191   (1)| 00:00:15 |
|* 21 |           INDEX RANGE SCAN           | SVRM_RADACCT_IDX          |    14 |       |     3   (0)| 00:00:01 |
|  22 |     TABLE ACCESS BY INDEX ROWID      | BM_CUSTOMER_TYPE          |     1 |    30 |     1   (0)| 00:00:01 |
|* 23 |      INDEX UNIQUE SCAN               | BM_CUSTOMER_TYPE_PK       |     1 |       |     0   (0)| 00:00:01 |
|* 24 |    INDEX RANGE SCAN                  | CUSTOMER_CONTACT_IDX      |     1 |       |     1   (0)| 00:00:01 |
------------------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   4 - access("S"."SERVICE_ID"="R"."SERVICE_ID")
   8 - access("CA"."CUSTOMER_ID"="C"."CUSTOMER_ID")
  10 - access("CA"."CONTACT_DICT_ID"=3 AND UPPER("VALUE") LIKE UPPER(:ADDRESS))
       filter(UPPER("VALUE") LIKE UPPER(:ADDRESS))
  11 - filter("C"."STATUS">0)
  12 - access("SCOPE"='client-groups-sms' AND "C"."GROUP_ID"="ID")
  13 - access("C"."CUSTOMER_ID"="S"."CUSTOMER_ID")
  16 - filter(TO_DATE(:PERIOD_BEG,'yyyy-mm-dd hh24:mi:ss')<=TO_DATE(:PERIOD_END,'yyyy-mm-dd hh24:mi:ss'))
  17 - filter("B"."TARIFFEL_ID" IS NOT NULL)
  19 - filter("R"."FRAMEDIPADDRESS"=:IP)
  20 - access("R"."ACCTSTARTTIME">=TO_DATE(:PERIOD_BEG,'yyyy-mm-dd hh24:mi:ss') AND
              "R"."ACCTSTARTTIME"<=TO_DATE(:PERIOD_END,'yyyy-mm-dd hh24:mi:ss'))
  21 - access("B"."RADACCTID"="R"."RADACCTID")
  23 - access("CT"."CUSTOMER_TYPE_ID"="C"."CUSTOMER_TYPE_ID")
  24 - access("CC"."CUSTOMER_ID"="C"."CUSTOMER_ID" AND "CC"."CONTACT_DICT_ID"=100)

Но из PHP-скрипта этот запрос по прежнему выполняется долго.
Как можно выяснить, в чем причина? Различные настройки окружения и сессии?

И как убедиться, что на результаты не влияет кеширование?
Я выполнял команды:
Код: plaintext
1.
2.
alter system flush shared_pool;
alter system flush buffer_cache;
и затем запускал запрос, в первый раз запрос выполнялся в течении десятка секунд.
Можно считать, что это чистый результат, без влияния кеширования?
...
Рейтинг: 0 / 0
Подскажите, как правильно составить запрос, чтобы эффективно использовались индексы
    #39326240
Фотография SY
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Alibek B.,

1. план от client tool не зависит.
2. оптимайзер достаточно умен чтобы проверять CA.CONTACT_DICT_ID = 3 один раз так-что незачем его тестировать :

Код: plsql
1.
2.
3.
4.
5.
join BM_CUSTOMER_CONTACT CA on (CA.CUSTOMER_ID = C.CUSTOMER_ID and CA.CONTACT_DICT_ID = 3)
where C.GROUP_ID in (select ID from TEMP.IDGROUPS where SCOPE = 'client-groups-sms')
and C.STATUS > 0
and R.FRAMEDIPADDRESS = :ip
and CA.CONTACT_DICT_ID = 3 and upper(CA.VALUE) like upper(:address)



3. убери хинты и проверь план и время выполнения.

SY.
...
Рейтинг: 0 / 0
Подскажите, как правильно составить запрос, чтобы эффективно использовались индексы
    #39326254
Alibek B
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Так хинты выключены (я убрал плюс).
Или речь про RESULT_CACHE?
...
Рейтинг: 0 / 0
Подскажите, как правильно составить запрос, чтобы эффективно использовались индексы
    #39326266
Фотография SY
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Alibek B.,

Код: plsql
1.
2.
3.
4.
5.
|* 19 |           TABLE ACCESS BY INDEX ROWID| RADACCT                   |    47 |  7802 |   150K  (1)| 00:30:12 |
|* 20 |            INDEX RANGE SCAN          | RADACCT_ACCTSTARTTIME_IDX |   236K|       |  1191   (1)| 00:00:15 |
  19 - filter("R"."FRAMEDIPADDRESS"=:IP)
  20 - access("R"."ACCTSTARTTIME">=TO_DATE(:PERIOD_BEG,'yyyy-mm-dd hh24:mi:ss') AND
              "R"."ACCTSTARTTIME"<=TO_DATE(:PERIOD_END,'yyyy-mm-dd hh24:mi:ss'))



Напрашивается добавить поле FRAMEDIPADDRESS к индексу RADACCT_ACCTSTARTTIME_IDX (хотя estimated плану на 100% доверять нельзя).

SY.
...
Рейтинг: 0 / 0
Подскажите, как правильно составить запрос, чтобы эффективно использовались индексы
    #39326271
Alibek B
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Убрал все хинты:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
------------------------------------------------------------------------------------------------------------------
| Id  | Operation                            | Name                      | Rows  | Bytes | Cost (%CPU)| Time     |
------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                     |                           |     1 |   997 |   151K  (1)| 00:30:16 |
|   1 |  TABLE ACCESS BY INDEX ROWID         | BM_CUSTOMER_CONTACT       |     1 |    31 |     2   (0)| 00:00:01 |
|   2 |   NESTED LOOPS                       |                           |     1 |   997 |   151K  (1)| 00:30:16 |
|   3 |    NESTED LOOPS                      |                           |     1 |   966 |   151K  (1)| 00:30:16 |
|*  4 |     HASH JOIN                        |                           |     1 |   936 |   151K  (1)| 00:30:16 |
|   5 |      TABLE ACCESS BY INDEX ROWID     | SERVICES                  |     5 |   145 |     7   (0)| 00:00:01 |
|   6 |       NESTED LOOPS                   |                           |    91 |  8554 |   150   (1)| 00:00:02 |
|   7 |        NESTED LOOPS                  |                           |    18 |  1170 |    61   (2)| 00:00:01 |
|*  8 |         HASH JOIN                    |                           |   310 | 14570 |    61   (2)| 00:00:01 |
|   9 |          TABLE ACCESS BY INDEX ROWID | BM_CUSTOMER_CONTACT       |   310 |  9610 |    46   (0)| 00:00:01 |
|* 10 |           INDEX RANGE SCAN           | CUSTOMER_CONTACT_VAL_IDX  |    56 |       |     3   (0)| 00:00:01 |
|* 11 |          TABLE ACCESS FULL           | CUSTOMERS                 |  9607 |   150K|    14   (0)| 00:00:01 |
|* 12 |         INDEX UNIQUE SCAN            | IDGROUPS_PK               |     1 |    18 |     0   (0)| 00:00:01 |
|* 13 |        INDEX RANGE SCAN              | SERV_CUSTOMER_IDX         |     7 |       |     1   (0)| 00:00:01 |
|  14 |      VIEW                            |                           |   662 |   544K|   151K  (1)| 00:30:14 |
|  15 |       HASH GROUP BY                  |                           |   662 |   117K|   151K  (1)| 00:30:14 |
|* 16 |        FILTER                        |                           |       |       |            |          |
|* 17 |         TABLE ACCESS BY INDEX ROWID  | BM_SERVICE_MONEY          |    14 |   224 |     6   (0)| 00:00:01 |
|  18 |          NESTED LOOPS                |                           |   662 |   117K|   151K  (1)| 00:30:14 |
|* 19 |           TABLE ACCESS BY INDEX ROWID| RADACCT                   |    47 |  7802 |   150K  (1)| 00:30:12 |
|* 20 |            INDEX RANGE SCAN          | RADACCT_ACCTSTARTTIME_IDX |   236K|       |  1191   (1)| 00:00:15 |
|* 21 |           INDEX RANGE SCAN           | SVRM_RADACCT_IDX          |    14 |       |     3   (0)| 00:00:01 |
|  22 |     TABLE ACCESS BY INDEX ROWID      | BM_CUSTOMER_TYPE          |     1 |    30 |     1   (0)| 00:00:01 |
|* 23 |      INDEX UNIQUE SCAN               | BM_CUSTOMER_TYPE_PK       |     1 |       |     0   (0)| 00:00:01 |
|* 24 |    INDEX RANGE SCAN                  | CUSTOMER_CONTACT_IDX      |     1 |       |     1   (0)| 00:00:01 |
------------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   4 - access("S"."SERVICE_ID"="R"."SERVICE_ID")
   8 - access("CA"."CUSTOMER_ID"="C"."CUSTOMER_ID")
  10 - access("CA"."CONTACT_DICT_ID"=3 AND UPPER("VALUE") LIKE UPPER(:ADDRESS))
       filter(UPPER("VALUE") LIKE UPPER(:ADDRESS))
  11 - filter("C"."STATUS">0)
  12 - access("SCOPE"='client-groups-sms' AND "C"."GROUP_ID"="ID")
  13 - access("C"."CUSTOMER_ID"="S"."CUSTOMER_ID")
  16 - filter(TO_DATE(:PERIOD_BEG,'yyyy-mm-dd hh24:mi:ss')<=TO_DATE(:PERIOD_END,'yyyy-mm-dd hh24:mi:ss'))
  17 - filter("B"."TARIFFEL_ID" IS NOT NULL)
  19 - filter("R"."FRAMEDIPADDRESS"=:IP)
  20 - access("R"."ACCTSTARTTIME">=TO_DATE(:PERIOD_BEG,'yyyy-mm-dd hh24:mi:ss') AND
              "R"."ACCTSTARTTIME"<=TO_DATE(:PERIOD_END,'yyyy-mm-dd hh24:mi:ss'))
  21 - access("B"."RADACCTID"="R"."RADACCTID")
  23 - access("CT"."CUSTOMER_TYPE_ID"="C"."CUSTOMER_TYPE_ID")
  24 - access("CC"."CUSTOMER_ID"="C"."CUSTOMER_ID" AND "CC"."CONTACT_DICT_ID"=100)

Кстати, если условие проверки на :address убрать, то PHP-скрипт результаты отображает довольно быстро.
А с дополнительной проверкой на :address (в которой задействован индекс) выполняется долго.
...
Рейтинг: 0 / 0
Подскажите, как правильно составить запрос, чтобы эффективно использовались индексы
    #39326273
Alibek B
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SYНапрашивается добавить поле FRAMEDIPADDRESS к индексу RADACCT_ACCTSTARTTIME_IDX (хотя estimated плану на 100% доверять нельзя).
В таблице RADACCT за 100М записей, я бы не хотел добавлять в нее индекс без особой необходимости.
Кроме того, если в запросе задается только эта проверка:
Код: plsql
1.
2.
3.
where C.GROUP_ID in (select ID from TEMP.IDGROUPS where SCOPE = 'client-groups-sms')
and C.STATUS > 0
and R.FRAMEDIPADDRESS = :ip


то запрос выполняется быстро (в том числе в PHP-скрипте).
А вот когда я к нему добавляю
Код: plsql
1.
and CA.CONTACT_DICT_ID = 3 and upper(CA.VALUE) like upper(:address)


то он выполняется долго.
...
Рейтинг: 0 / 0
Подскажите, как правильно составить запрос, чтобы эффективно использовались индексы
    #39326276
Фотография SY
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Alibek B.Так хинты выключены (я убрал плюс).
Или речь про RESULT_CACHE?

Не заметил + убран в хинтe NL. А что тут дает RESULT_CACHE? В плане не вижу ни

Код: plsql
1.
|   x |  RESULT CACHE            | xxxxxxxxxxxxxxxxxxxxxxxxxxx |       | ... |       |       |



ни:

Код: plsql
1.
2.
Result Cache Information (identified by operation id):
------------------------------------------------------



SY.
...
Рейтинг: 0 / 0
Подскажите, как правильно составить запрос, чтобы эффективно использовались индексы
    #39326281
Alibek B
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вот план без проверки на :address (только с :ip)
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
--------------------------------------------------------------------------------------------------------------------
| Id  | Operation                              | Name                      | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                       |                           |    18 |  7146 |   151K  (1)| 00:30:18 |
|   1 |  HASH GROUP BY                         |                           |    18 |  7146 |   151K  (1)| 00:30:18 |
|*  2 |   FILTER                               |                           |       |       |            |          |
|*  3 |    HASH JOIN                           |                           |    18 |  7146 |   151K  (1)| 00:30:18 |
|   4 |     TABLE ACCESS BY INDEX ROWID        | BM_CUSTOMER_CONTACT       |     1 |    43 |     2   (0)| 00:00:01 |
|   5 |      NESTED LOOPS                      |                           |    18 |  6444 |   151K  (1)| 00:30:18 |
|   6 |       NESTED LOOPS                     |                           |    24 |  7560 |   151K  (1)| 00:30:17 |
|   7 |        NESTED LOOPS                    |                           |    38 | 10336 |   151K  (1)| 00:30:16 |
|*  8 |         HASH JOIN                      |                           |   664 |   162K|   151K  (1)| 00:30:16 |
|*  9 |          HASH JOIN                     |                           |   664 |   144K|   151K  (1)| 00:30:16 |
|* 10 |           TABLE ACCESS BY INDEX ROWID  | BM_SERVICE_MONEY          |    14 |   224 |     6   (0)| 00:00:01 |
|  11 |            NESTED LOOPS                |                           |   662 |   117K|   151K  (1)| 00:30:14 |
|* 12 |             TABLE ACCESS BY INDEX ROWID| RADACCT                   |    47 |  7802 |   150K  (1)| 00:30:12 |
|* 13 |              INDEX RANGE SCAN          | RADACCT_ACCTSTARTTIME_IDX |   236K|       |  1191   (1)| 00:00:15 |
|* 14 |             INDEX RANGE SCAN           | SVRM_RADACCT_IDX          |    14 |       |     3   (0)| 00:00:01 |
|  15 |           TABLE ACCESS FULL            | SERVICES                  | 47772 |  1912K|   194   (1)| 00:00:03 |
|* 16 |          TABLE ACCESS FULL             | CUSTOMERS                 |  9607 |   262K|    14   (0)| 00:00:01 |
|* 17 |         INDEX UNIQUE SCAN              | IDGROUPS_PK               |     1 |    21 |     0   (0)| 00:00:01 |
|  18 |        TABLE ACCESS BY INDEX ROWID     | BM_CUSTOMER_CONTACT       |     1 |    43 |     2   (0)| 00:00:01 |
|* 19 |         INDEX RANGE SCAN               | CUSTOMER_CONTACT_IDX      |     1 |       |     1   (0)| 00:00:01 |
|* 20 |       INDEX RANGE SCAN                 | CUSTOMER_CONTACT_IDX      |     1 |       |     1   (0)| 00:00:01 |
|  21 |     TABLE ACCESS FULL                  | BM_CUSTOMER_TYPE          |     9 |   351 |     3   (0)| 00:00:01 |
--------------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   2 - filter(TO_DATE(:PERIOD_BEG,'yyyy-mm-dd hh24:mi:ss')<=TO_DATE(:PERIOD_END,'yyyy-mm-dd hh24:mi:ss'))
   3 - access("CT"."CUSTOMER_TYPE_ID"="C"."CUSTOMER_TYPE_ID")
   8 - access("C"."CUSTOMER_ID"="S"."CUSTOMER_ID")
   9 - access("S"."SERVICE_ID"="B"."SERVICE_ID")
  10 - filter("B"."TARIFFEL_ID" IS NOT NULL)
  12 - filter("R"."FRAMEDIPADDRESS"=:IP)
  13 - access("R"."ACCTSTARTTIME">=TO_DATE(:PERIOD_BEG,'yyyy-mm-dd hh24:mi:ss') AND
              "R"."ACCTSTARTTIME"<=TO_DATE(:PERIOD_END,'yyyy-mm-dd hh24:mi:ss'))
  14 - access("B"."RADACCTID"="R"."RADACCTID")
  16 - filter("C"."STATUS">0)
  17 - access("SCOPE"='client-groups-sms' AND "C"."GROUP_ID"="ID")
  19 - access("CA"."CUSTOMER_ID"="C"."CUSTOMER_ID" AND "CA"."CONTACT_DICT_ID"=3)
  20 - access("CC"."CUSTOMER_ID"="C"."CUSTOMER_ID" AND "CC"."CONTACT_DICT_ID"=100)


SYА что тут дает RESULT_CACHE?
Версии:
Oracle Database 10g Release 10.2.0.4.0 - 64bit Production
PL/SQL Release 10.2.0.4.0 - Production
CORE 10.2.0.4.0 Production
TNS for Linux: Version 10.2.0.4.0 - Production
NLSRTL Version 10.2.0.4.0 - Production

Возможно в моей версии этот хинт недоступен или отключен.
...
Рейтинг: 0 / 0
Подскажите, как правильно составить запрос, чтобы эффективно использовались индексы
    #39326285
Фотография SY
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Alibek B.,

Я не предлагал новый индекс. Я педлагал добавить поле к существующему. Тогда отпадет необходимость в TABLE ACCESS BY INDEX ROWID. Насчет "А вот когда я к нему добавляю" - зачем добавлять условие CA.CONTACT_DICT_ID = 3 дважды - один раз в ON а торой раз в WHERE? Масло масляное? Контроьный выстрел?

SY.
...
Рейтинг: 0 / 0
Подскажите, как правильно составить запрос, чтобы эффективно использовались индексы
    #39326290
Фотография SY
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Alibek B.Возможно в моей версии этот хинт недоступен или отключен.

Query result cache появился, если не ошибаюсь, в 11g.

SY.
...
Рейтинг: 0 / 0
Подскажите, как правильно составить запрос, чтобы эффективно использовались индексы
    #39326295
Alibek B
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SYЯ педлагал добавить поле к существующему.
Но в системе часто требуется быстрый доступ по ACCTSTARTTIME (без учета FRAMEDIPADDRESS).
Или в этом случае составной индекс тоже будет использоваться?
...
Рейтинг: 0 / 0
Подскажите, как правильно составить запрос, чтобы эффективно использовались индексы
    #39326341
Фотография SY
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Alibek B.Но в системе часто требуется быстрый доступ по ACCTSTARTTIME (без учета FRAMEDIPADDRESS).
Или в этом случае составной индекс тоже будет использоваться?

Будет, разве-что FRAMEDIPADDRESS очень длинноe поле, хотя судя по имени это IP адрес. В любом случае тестировать всeгда надо.

SY.
...
Рейтинг: 0 / 0
Подскажите, как правильно составить запрос, чтобы эффективно использовались индексы
    #39326419
Alibek B
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ок, буду иметь ввиду этот способ, как запасной.

А как мне найти причину, почему один и тот же запрос, с одними и теми же параметрами в TOAD выполняется быстро, а в PHP-скрипте долго?
Я подсунул в PHP-скрипт explain plan, получил такой результат:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
-------------------------------------------------------------------------------------------------------------------
| Id  | Operation                             | Name                      | Rows  | Bytes | Cost (%CPU)| Time     |
-------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                      |                           |     1 |   989 |   151K  (1)| 00:30:16 |
|   1 |  SORT ORDER BY                        |                           |     1 |   989 |   151K  (1)| 00:30:16 |
|   2 |   TABLE ACCESS BY INDEX ROWID         | BM_CUSTOMER_CONTACT       |     1 |    31 |     2   (0)| 00:00:01 |
|   3 |    NESTED LOOPS                       |                           |     1 |   989 |   151K  (1)| 00:30:16 |
|   4 |     NESTED LOOPS                      |                           |     1 |   958 |   151K  (1)| 00:30:16 |
|*  5 |      HASH JOIN                        |                           |     1 |   928 |   151K  (1)| 00:30:16 |
|   6 |       TABLE ACCESS BY INDEX ROWID     | SERVICES                  |     5 |   145 |     7   (0)| 00:00:01 |
|   7 |        NESTED LOOPS                   |                           |    91 |  8554 |   150   (1)| 00:00:02 |
|   8 |         NESTED LOOPS                  |                           |    18 |  1170 |    61   (2)| 00:00:01 |
|*  9 |          HASH JOIN                    |                           |   310 | 14570 |    61   (2)| 00:00:01 |
|  10 |           TABLE ACCESS BY INDEX ROWID | BM_CUSTOMER_CONTACT       |   310 |  9610 |    46   (0)| 00:00:01 |
|* 11 |            INDEX RANGE SCAN           | CUSTOMER_CONTACT_VAL_IDX  |    56 |       |     3   (0)| 00:00:01 |
|* 12 |           TABLE ACCESS FULL           | CUSTOMERS                 |  9607 |   150K|    14   (0)| 00:00:01 |
|* 13 |          INDEX UNIQUE SCAN            | IDGROUPS_PK               |     1 |    18 |     0   (0)| 00:00:01 |
|* 14 |         INDEX RANGE SCAN              | SERV_CUSTOMER_IDX         |     7 |       |     1   (0)| 00:00:01 |
|  15 |       VIEW                            |                           |   662 |   539K|   151K  (1)| 00:30:14 |
|  16 |        HASH GROUP BY                  |                           |   662 |   117K|   151K  (1)| 00:30:14 |
|* 17 |         FILTER                        |                           |       |       |            |          |
|* 18 |          TABLE ACCESS BY INDEX ROWID  | BM_SERVICE_MONEY          |    14 |   224 |     6   (0)| 00:00:01 |
|  19 |           NESTED LOOPS                |                           |   662 |   117K|   151K  (1)| 00:30:14 |
|* 20 |            TABLE ACCESS BY INDEX ROWID| RADACCT                   |    47 |  7802 |   150K  (1)| 00:30:12 |
|* 21 |             INDEX RANGE SCAN          | RADACCT_ACCTSTARTTIME_IDX |   236K|       |  1191   (1)| 00:00:15 |
|* 22 |            INDEX RANGE SCAN           | SVRM_RADACCT_IDX          |    14 |       |     3   (0)| 00:00:01 |
|  23 |      TABLE ACCESS BY INDEX ROWID      | BM_CUSTOMER_TYPE          |     1 |    30 |     1   (0)| 00:00:01 |
|* 24 |       INDEX UNIQUE SCAN               | BM_CUSTOMER_TYPE_PK       |     1 |       |     0   (0)| 00:00:01 |
|* 25 |     INDEX RANGE SCAN                  | CUSTOMER_CONTACT_IDX      |     1 |       |     1   (0)| 00:00:01 |
-------------------------------------------------------------------------------------------------------------------
 
Predicate Information (identified by operation id):
---------------------------------------------------
 
   5 - access("S"."SERVICE_ID"="R"."SERVICE_ID")
   9 - access("CA"."CUSTOMER_ID"="C"."CUSTOMER_ID")
  11 - access("CA"."CONTACT_DICT_ID"=3 AND UPPER("VALUE") LIKE UPPER(:ADDRESS))
       filter(UPPER("VALUE") LIKE UPPER(:ADDRESS))
  12 - filter("C"."STATUS">0)
  13 - access("SCOPE"='client-groups-sms' AND "C"."GROUP_ID"="ID")
  14 - access("C"."CUSTOMER_ID"="S"."CUSTOMER_ID")
  17 - filter(TO_DATE(:PERIOD_BEG,'yyyy-mm-dd hh24:mi:ss')<=TO_DATE(:PERIOD_END,'yyyy-mm-dd hh24:mi:ss'))
  18 - filter("B"."TARIFFEL_ID" IS NOT NULL)
  20 - filter("R"."FRAMEDIPADDRESS"=:IP)
  21 - access("R"."ACCTSTARTTIME">=TO_DATE(:PERIOD_BEG,'yyyy-mm-dd hh24:mi:ss') AND 
              "R"."ACCTSTARTTIME"<=TO_DATE(:PERIOD_END,'yyyy-mm-dd hh24:mi:ss'))
  22 - access("B"."RADACCTID"="R"."RADACCTID")
  24 - access("CT"."CUSTOMER_TYPE_ID"="C"."CUSTOMER_TYPE_ID")
  25 - access("CC"."CUSTOMER_ID"="C"."CUSTOMER_ID" AND "CC"."CONTACT_DICT_ID"=100)
Насколько могу судить, в плане особых отличий нет.
...
Рейтинг: 0 / 0
Подскажите, как правильно составить запрос, чтобы эффективно использовались индексы
    #39326454
Alibek B
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Оказывается дело не совсем в скрипте.
В PHP выполняется такой запрос:
Код: plsql
1.
2.
3.
4.
5.
6.
select * from (
select ... --запрос1
union all
select ... --запрос2
)
order by SESSION_START, CLIENT, LOGIN


То есть два запроса, соединенных через union all и отсортированных.
В TOAD этот составной запрос выполняется быстро, также как по отдельности запрос1 и запрос2.
В PHP-скрипте каждый запрос по отдельности выполняется быстро, даже если он обернут во внешний запрос с сортировкой (то есть select * from (запрос1) order by ...).
А вот составной запрос в PHP-скрипте выполняется долго.

Из-за чего может быть такое поведение?
Вот план составного запроса при выполнении его в PHP-скрипте:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
-----------------------------------------------------------------------------------------------------------------------
| Id  | Operation                                 | Name                      | Rows  | Bytes | Cost (%CPU)| Time     |
-----------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                          |                           |     2 |  3026 |   151K  (1)| 00:30:19 |
|   1 |  VIEW                                     |                           |     2 |  3026 |   151K  (1)| 00:30:19 |
|   2 |   UNION-ALL                               |                           |       |       |            |          |
|*  3 |    FILTER                                 |                           |       |       |            |          |
|   4 |     TABLE ACCESS BY INDEX ROWID           | BM_CUSTOMER_CONTACT       |     1 |    31 |     2   (0)| 00:00:01 |
|   5 |      NESTED LOOPS                         |                           |     1 |   406 |   190   (2)| 00:00:03 |
|   6 |       NESTED LOOPS                        |                           |     1 |   375 |   188   (2)| 00:00:03 |
|   7 |        NESTED LOOPS OUTER                 |                           |     4 |   888 |   180   (2)| 00:00:03 |
|   8 |         NESTED LOOPS                      |                           |     4 |   648 |   172   (2)| 00:00:03 |
|*  9 |          HASH JOIN ANTI                   |                           |     4 |   580 |   167   (2)| 00:00:03 |
|* 10 |           TABLE ACCESS BY INDEX ROWID     | SERVICES                  |     2 |    82 |     7   (0)| 00:00:01 |
|  11 |            NESTED LOOPS                   |                           |    35 |  4760 |   155   (2)| 00:00:02 |
|* 12 |             HASH JOIN                     |                           |    18 |  1710 |    66   (5)| 00:00:01 |
|  13 |              TABLE ACCESS BY INDEX ROWID  | BM_CUSTOMER_CONTACT       |   310 |  9610 |    46   (0)| 00:00:01 |
|* 14 |               INDEX RANGE SCAN            | CUSTOMER_CONTACT_VAL_IDX  |    56 |       |     3   (0)| 00:00:01 |
|  15 |              NESTED LOOPS                 |                           |   544 | 34816 |    19  (11)| 00:00:01 |
|* 16 |               HASH JOIN                   |                           |  9607 |   431K|    18   (6)| 00:00:01 |
|  17 |                TABLE ACCESS FULL          | BM_CUSTOMER_TYPE          |     9 |   270 |     3   (0)| 00:00:01 |
|* 18 |                TABLE ACCESS FULL          | CUSTOMERS                 |  9607 |   150K|    14   (0)| 00:00:01 |
|* 19 |               INDEX UNIQUE SCAN           | IDGROUPS_PK               |     1 |    18 |     0   (0)| 00:00:01 |
|* 20 |             INDEX RANGE SCAN              | SERV_CUSTOMER_IDX         |     7 |       |     1   (0)| 00:00:01 |
|  21 |           TABLE ACCESS BY INDEX ROWID     | BM_TARIFFEL               |   254 |  2286 |    12   (0)| 00:00:01 |
|* 22 |            INDEX RANGE SCAN               | TAREL_TYPE_IDX            |   254 |       |     1   (0)| 00:00:01 |
|  23 |          TABLE ACCESS BY INDEX ROWID      | CURSESSIONS               |     1 |    17 |     2   (0)| 00:00:01 |
|* 24 |           INDEX RANGE SCAN                | CURSESS_SERVICE_IDX       |     1 |       |     1   (0)| 00:00:01 |
|* 25 |         TABLE ACCESS BY INDEX ROWID       | RADREPLY                  |     1 |    60 |     3   (0)| 00:00:01 |
|* 26 |          INDEX RANGE SCAN                 | RADREPLY_SERVICE_IDX      |     8 |       |     1   (0)| 00:00:01 |
|* 27 |        TABLE ACCESS BY INDEX ROWID        | RADACCT                   |     1 |   153 |     2   (0)| 00:00:01 |
|* 28 |         INDEX UNIQUE SCAN                 | RADACCT_PK                |     1 |       |     1   (0)| 00:00:01 |
|* 29 |       INDEX RANGE SCAN                    | CUSTOMER_CONTACT_IDX      |     1 |       |     1   (0)| 00:00:01 |
|  30 |    HASH GROUP BY                          |                           |     1 |   410 |   151K  (1)| 00:30:17 |
|* 31 |     FILTER                                |                           |       |       |            |          |
|  32 |      TABLE ACCESS BY INDEX ROWID          | BM_CUSTOMER_CONTACT       |     1 |    43 |     2   (0)| 00:00:01 |
|  33 |       NESTED LOOPS                        |                           |     1 |   410 |   151K  (1)| 00:30:17 |
|  34 |        NESTED LOOPS                       |                           |     1 |   367 |   151K  (1)| 00:30:17 |
|  35 |         NESTED LOOPS                      |                           |     1 |   351 |   151K  (1)| 00:30:17 |
|* 36 |          HASH JOIN                        |                           |     1 |   312 |   151K  (1)| 00:30:17 |
|  37 |           NESTED LOOPS                    |                           |    38 | 10222 |   151K  (1)| 00:30:16 |
|* 38 |            HASH JOIN                      |                           |   664 |   162K|   151K  (1)| 00:30:16 |
|* 39 |             HASH JOIN                     |                           |   664 |   144K|   151K  (1)| 00:30:16 |
|* 40 |              TABLE ACCESS BY INDEX ROWID  | BM_SERVICE_MONEY          |    14 |   224 |     6   (0)| 00:00:01 |
|  41 |               NESTED LOOPS                |                           |   662 |   117K|   151K  (1)| 00:30:14 |
|* 42 |                TABLE ACCESS BY INDEX ROWID| RADACCT                   |    47 |  7802 |   150K  (1)| 00:30:12 |
|* 43 |                 INDEX RANGE SCAN          | RADACCT_ACCTSTARTTIME_IDX |   236K|       |  1191   (1)| 00:00:15 |
|* 44 |                INDEX RANGE SCAN           | SVRM_RADACCT_IDX          |    14 |       |     3   (0)| 00:00:01 |
|  45 |              TABLE ACCESS FULL            | SERVICES                  | 47772 |  1912K|   194   (1)| 00:00:03 |
|* 46 |             TABLE ACCESS FULL             | CUSTOMERS                 |  9607 |   262K|    14   (0)| 00:00:01 |
|* 47 |            INDEX UNIQUE SCAN              | IDGROUPS_PK               |     1 |    18 |     0   (0)| 00:00:01 |
|  48 |           TABLE ACCESS BY INDEX ROWID     | BM_CUSTOMER_CONTACT       |   310 | 13330 |    46   (0)| 00:00:01 |
|* 49 |            INDEX RANGE SCAN               | CUSTOMER_CONTACT_VAL_IDX  |    56 |       |     3   (0)| 00:00:01 |
|  50 |          TABLE ACCESS BY INDEX ROWID      | BM_CUSTOMER_TYPE          |     1 |    39 |     1   (0)| 00:00:01 |
|* 51 |           INDEX UNIQUE SCAN               | BM_CUSTOMER_TYPE_PK       |     1 |       |     0   (0)| 00:00:01 |
|* 52 |         INDEX UNIQUE SCAN                 | GROUP_PK                  |     1 |    16 |     0   (0)| 00:00:01 |
|* 53 |        INDEX RANGE SCAN                   | CUSTOMER_CONTACT_IDX      |     1 |       |     1   (0)| 00:00:01 |
-----------------------------------------------------------------------------------------------------------------------
 
Predicate Information (identified by operation id):
---------------------------------------------------
 
   3 - filter(TO_DATE(:PERIOD_BEG,'yyyy-mm-dd hh24:mi:ss')<=TO_DATE(:PERIOD_END,'yyyy-mm-dd hh24:mi:ss'))
   9 - access("TARIFF_ID"="S"."TARIFF_ID")
  10 - filter("S"."TYPE_ID"=14 AND "S"."STATUS"<>(-20))
  12 - access("CA"."CUSTOMER_ID"="C"."CUSTOMER_ID")
  14 - access("CA"."CONTACT_DICT_ID"=3 AND UPPER("VALUE") LIKE UPPER(:ADDRESS))
       filter(UPPER("VALUE") LIKE UPPER(:ADDRESS))
  16 - access("CT"."CUSTOMER_TYPE_ID"="C"."CUSTOMER_TYPE_ID")
  18 - filter("C"."STATUS">0)
  19 - access("SCOPE"='client-groups-sms' AND "C"."GROUP_ID"="ID")
  20 - access("S"."CUSTOMER_ID"="C"."CUSTOMER_ID")
  22 - access("TARIFFEL_TYPE_ID"=908)
  24 - access("Z"."SERVICE_ID"="S"."SERVICE_ID")
  25 - filter("SR"."ATTRIBUTE"(+)='Framed-IP-Address' AND "SR"."DATE_END"(+) IS NULL AND 
              "SR"."DATE_BEG"(+)<=SYSDATE@!)
  26 - access("SR"."SERVICE_ID"(+)="S"."SERVICE_ID")
  27 - filter("R"."ACCTSTARTTIME">=TO_DATE(:PERIOD_BEG,'yyyy-mm-dd hh24:mi:ss') AND 
              "R"."ACCTSTARTTIME"<=TO_DATE(:PERIOD_END,'yyyy-mm-dd hh24:mi:ss') AND 
              COALESCE("R"."FRAMEDIPADDRESS","SR"."VALUE",'-')=:IP)
  28 - access("R"."RADACCTID"="Z"."RADACCTID")
  29 - access("CC"."CUSTOMER_ID"="C"."CUSTOMER_ID" AND "CC"."CONTACT_DICT_ID"=100)
  31 - filter(TO_DATE(:PERIOD_BEG,'yyyy-mm-dd hh24:mi:ss')<=TO_DATE(:PERIOD_END,'yyyy-mm-dd hh24:mi:ss'))
  36 - access("CA"."CUSTOMER_ID"="C"."CUSTOMER_ID")
  38 - access("C"."CUSTOMER_ID"="S"."CUSTOMER_ID")
  39 - access("S"."SERVICE_ID"="B"."SERVICE_ID")
  40 - filter("B"."TARIFFEL_ID" IS NOT NULL)
  42 - filter("R"."FRAMEDIPADDRESS"=:IP)
  43 - access("R"."ACCTSTARTTIME">=TO_DATE(:PERIOD_BEG,'yyyy-mm-dd hh24:mi:ss') AND 
              "R"."ACCTSTARTTIME"<=TO_DATE(:PERIOD_END,'yyyy-mm-dd hh24:mi:ss'))
  44 - access("B"."RADACCTID"="R"."RADACCTID")
  46 - filter("C"."STATUS">0)
  47 - access("SCOPE"='client-groups-sms' AND "C"."GROUP_ID"="ID")
  49 - access("CA"."CONTACT_DICT_ID"=3 AND UPPER("VALUE") LIKE UPPER(:ADDRESS))
       filter(UPPER("VALUE") LIKE UPPER(:ADDRESS))
  51 - access("CT"."CUSTOMER_TYPE_ID"="C"."CUSTOMER_TYPE_ID")
  52 - access("CG"."GROUP_ID"="C"."GROUP_ID")
  53 - access("CC"."CUSTOMER_ID"="C"."CUSTOMER_ID" AND "CC"."CONTACT_DICT_ID"=100)

В TOAD план точно такой-же (специально сохранял два плана в текстовые файлы и сравнивал).
Но в TOAD запрос отрабатывает быстро.
...
Рейтинг: 0 / 0
Подскажите, как правильно составить запрос, чтобы эффективно использовались индексы
    #39326539
Фотография SY
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Alibek B.Но в TOAD запрос отрабатывает быстро.

Toad выдает на гора первые строки результата, пoсему и может казаться бысто. Ты в Toad'e нажми пимпочку "до упора", вот тогда и узнаешь полное время всех fetch'ей.

SY.
...
Рейтинг: 0 / 0
Подскажите, как правильно составить запрос, чтобы эффективно использовались индексы
    #39326665
Alibek B
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Конкретно в последнем запросе возвращалось около десятка строк, так что дело точно не в этом (TOAD загружает по 500 строк).
Ну и в случае PHP-скрипта запрос у меня выполняется дважды — первый раз select count(*) from <sql> (чтобы посчитать число строк), второй раз select *, rn from (select *, rownum rn from <sql> where rownum<=...) where rn>=... (чтобы отобразить выбранную страницу). До второго раза PHP-скрипт не доходит, зависает на select count(*), в котором возвращается только одна строка.

Подобные побочные эффекты могут быть из-за union all? Или причина точно не в этом?
В крайнем случае я завтра попробую обойтись без union, выполняя запросы отдельно и объединяя результаты уже на клиентской стороне.
...
Рейтинг: 0 / 0
Подскажите, как правильно составить запрос, чтобы эффективно использовались индексы
    #39326712
Фотография SY
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Так добaвь

COUNT(*) OVER() cnt

к select list и первый-же фетч покажет число строк.

SY.
...
Рейтинг: 0 / 0
Подскажите, как правильно составить запрос, чтобы эффективно использовались индексы
    #39340701
Alibek B
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Спасибо, не знал про такое, так действительно проще.

У меня еще такой вопрос.
Есть запрос с такой строкой:
Код: plsql
1.
where trunc(PA.MOMENT) = trunc(sysdate)


Запрос возвращает около десятка строк, выполняется моментально. PA.MOMENT проиндексирован.

Если сделать так:
Код: plsql
1.
where PA.MOMENT > CB.CHANGED


то запрос выполняется 10-15 секунд, возвращает пару десятков строк. CB.CHANGED не проиндексирован.
В таблице PA строк много, в таблице CB строк меньше тысячи.

Может быть такая разница из-за того, что CB.CHANGED неиндексирован?
Или нужно изучать план выполнения?
...
Рейтинг: 0 / 0
25 сообщений из 60, страница 2 из 3
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Подскажите, как правильно составить запрос, чтобы эффективно использовались индексы
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]