#sql #oracle
Есть запрос: SELECT zxp.rulon.ukey, n, nz, bz, zxp.rulon.ms, tz, ts, round(hz,2) HZ, hdm, hdp, zxp.rulon.h1, l, round(pf,2) PF, pt, pu, pdm, pdp, pbm, pbp, pe, zxp.mc.ukey, naim, LDM, LDP, LBM, LBP, H0, tr, tv, DOP, zxp.graph.irez as Broken, K_Z as Brigade FROM zxp.rulon, zxp.mc, zxp.graph WHERE ts BETWEEN to_date('02.01.2016 7:00:00', 'dd.mm.yyyy hh24:mi:ss') AND to_date('02.01.2016 15:00:00', 'dd.mm.yyyy hh24:mi:ss') AND zxp.rulon.ms = zxp.mc.ukey AND zxp.rulon.ukey = zxp.graph.u_rul AND k = ( SELECT min(k) FROM zxp.Graph WHERE zxp.rulon.ukey = zxp.graph.u_rul ) ORDER BY ts Но его выполнение занимает от 4 секунд и выше. Можно ли его оптимизировать? zxp.Rulon: UKEY NUMBER N NUMBER ADR NUMBER NZ NUMBER MS NUMBER TR DATE TZ DATE TV DATE TS DATE TM NUMBER SK NUMBER DOP NUMBER BZ NUMBER HZ NUMBER HZZ NUMBER HDM NUMBER HDP NUMBER H0 NUMBER H1 NUMBER L NUMBER LDM NUMBER LDP NUMBER LBM NUMBER LBP NUMBER PF NUMBER PT NUMBER PDM NUMBER PDP NUMBER PBM NUMBER PBP NUMBER PU NUMBER PE NUMBER L_1 NUMBER L_2 NUMBER L_3 NUMBER L_4 NUMBER H1S NUMBER H2S NUMBER H3S NUMBER H4SI NUMBER H1SI NUMBER T1S NUMBER T2S NUMBER T3S NUMBER T4S NUMBER D1 NUMBER D2 NUMBER D3 NUMBER D4 NUMBER GH4N NUMBER GH4Z NUMBER GH4S NUMBER GH1Z NUMBER GH1S NUMBER L4 NUMBER D_RR NUMBER D_RV NUMBER K_T NUMBER K_Z NUMBER F_REZ1 NUMBER F_REZ2 NUMBER F_REZ3 NUMBER F_REZ4 NUMBER I_REZ1 NUMBER I_REZ2 NUMBER I_REZ3 NUMBER I_REZ4 NUMBER Graph: T2 NUMBER T3 NUMBER T4 NUMBER DL NUMBER IREZ NUMBER FREZ NUMBER LOGBITS NUMBER UKEY NUMBER U_RUL NUMBER K NUMBER T DATE H4 NUMBER H1 NUMBER V1 NUMBER V2 NUMBER V3 NUMBER V4 NUMBER Это то что вы просили ? структура таблицы ? Plan hash value: 515981838 -------------------------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)| Time | -------------------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1653 | 663K| | 332 (2)| 00:00:04 | | 1 | SORT ORDER BY | | 1653 | 663K| 1672K| 332 (2)| 00:00:04 | |* 2 | VIEW | VW_WIF_1 | 1653 | 663K| | 184 (2)| 00:00:03 | | 3 | WINDOW SORT | | 1653 | 384K| 872K| 184 (2)| 00:00:03 | |* 4 | FILTER | | | | | | | | 5 | TABLE ACCESS BY INDEX ROWID | GRAPH | 3320 | 110K| | 88 (2)| 00:00:02 | | 6 | NESTED LOOPS | | 1653 | 384K| | 94 (2)| 00:00:02 | |* 7 | HASH JOIN | | 1 | 204 | | 7 (15)| 00:00:01 | | 8 | TABLE ACCESS BY INDEX ROWID| RULON | 1 | 195 | | 3 (0)| 00:00:01 | |* 9 | INDEX RANGE SCAN | I_RUL | 1 | | | 2 (0)| 00:00:01 | | 10 | TABLE ACCESS FULL | MC | 45 | 405 | | 3 (0)| 00:00:01 | |* 11 | INDEX RANGE SCAN | GRAPH_RUL | 3391 | | | 12 (0)| 00:00:01 | -------------------------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 2 - filter("VW_COL_33" IS NOT NULL) 4 - filter(TO_DATE('02.01.2016 15:00:00','dd.mm.yy hh24:mi:ss')>=TO_DATE('2016-01-02 07:00:00', 'yyyy-mm-dd hh24:mi:ss')) 7 - access("RULON"."MS"="MC"."UKEY") 9 - access("TS">=TO_DATE('2016-01-02 07:00:00', 'yyyy-mm-dd hh24:mi:ss') AND "TS"<=TO_DATE('02.01.2016 15:00:00','dd.mm.yy hh24:mi:ss')) 11 - access("RULON"."UKEY"="GRAPH"."U_RUL") Индекс таблиц RULON: Таблица Индекс Тип Колонки RULON RUL_UN UNIQUE UKEY RULON I_RUL NONUNIQUE TS GRAPH: GRAPH GRAPH_RUL NONUNIQUE U_RUL
Ответы
Ответ 1
Оптимизатор оракла походу построил максимально эффективный план для данного запроса. Он по GRAPH идет всего один раз, строя оконную функцию и выбирая по ней запись с минимальным K. Но для поиска этого минимума ему приходится пройти много записей графа и просто изменением запроса это не лечится. Как решения вижу: Хранить минимальный K к рулону (и вести его триггерами), что бы исключить необходимость поиска минимума в графе. Как минус - собственно необходимость создания триггера, который при добавлении/модификации записей в GRAPH должен будет сверять K с хранимым в рулоне и менять его там, при необходимости. Построить на GRAPH составной индекс по колонкам (U_RUL, K), тогда оракл должен сходу находить записи с минимальным K, не заглядывая в данные. Как минус - индекс на 373кк записей займет много места и несколько замедлит создание новых записей в таблице GRAPH.
Комментариев нет:
Отправить комментарий