Question:
There is a request:
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
But its execution takes 4 seconds or more. Can you optimize it?
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
Is this what you asked for? table structure?
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 table index:
Таблица Индекс Тип Колонки
RULON RUL_UN UNIQUE UKEY
RULON I_RUL NONUNIQUE TS
GRAPH:
GRAPH GRAPH_RUL NONUNIQUE U_RUL
Answer:
The Oracle optimizer has built the most efficient plan for the given query. He goes along GRAPH only once, constructing a window function and choosing an entry with a minimum K
using it. But to find this minimum, he has to go through many records of the graph and simply changing the query does not cure it.
As solutions I see:
-
Store the minimum
K
to the roll (and lead it by triggers) to eliminate the need to search for the minimum in the graph. As a minus – the actual need to create a trigger, which, when adding / modifying records inGRAPH
, will have to compare K with the one stored in the roll and change it there, if necessary. -
Construct a composite index on columns
(U_RUL, K)
onGRAPH
, then the Oracle should immediately find records with a minimumK
, without looking into the data. As a minus – an index on 373kk records will take up a lot of space and will somewhat slow down the creation of new records in theGRAPH
table.