大家好,我需要优化此查询:
SELECT *
FROM
(SELECT r.*, ROWNUM RNUM
FROM (
SELECT t0.RISK , t3.AMOUNT, t3.DATE_TIME , t0.ID
FROM
REACTION.ALERT t0, REACTION.INVESTIGATION t1,
REACTION.CLASSIFICATION_TYPE t2, REACTION.TRANS t3,
REACTION.FRAUD_TYPE t4, REACTION.CARD t5
WHERE (
(NOT EXISTS (SELECT 1 FROM REACTION.INVESTIGATION WHERE REACTION.INVESTIGATION.ALERT_ID = t0.ID) OR
t1.CLASSIFICATION_TYPE_ID IS NULL OR t2.CLASSIFICATION_TYPE = 2) AND
t0.MODULE_TYPE = 0 AND
t0.PROCESSING_MODE_TYPE = 1 AND
t0.ISS_INST IN (1201, 1101)
) AND
t0.ID = t1.ALERT_ID(+) AND
t0.TRANSACTION_ID = t3.ID AND
t1.CLASSIFICATION_TYPE_ID = t2.ID(+) AND
t1.FRAUD_TYPE_ID = t4.ID(+) AND
t3.HPAN = t5.HPAN(+)
ORDER BY t0.RISK DESC, t3.AMOUNT DESC, t3.DATE_TIME DESC, t0.ID DESC
) r
WHERE ROWNUM <= 120)
WHERE RNUM > 100;
但是如何在colums上使用所有订单上的索引( t0.RISK DESC,t3.AMOUNT DESC,t3.DATE_TIME DESC,t0.ID DESC )? 我试图创建2个索引:
create index risk_idx on ALERT (risk,id);
create index amount_date_idx on TRANS (AMOUNT,DATE_TIME);
但我仍然对TRANS和ALERT表进行全面扫描,但是如果我将排序更改为 ORDER BY t0.RISK DESC,则t0.ID DESC : risk_idx 索引有效并且查询执行得更快。 此外,我试图单独为这4列中的每一列设置索引:
create index risk_idx on ALERT (risk,1);
create index amount_idx on TRANS (amount,1);
create index date_time_idx on TRANS (DATE_TIME,1);
但那也没有帮助(
附:列ALERT.RISK, TRANS.AMOUNT , TRANS.DATE_TIME
具有 NULLABLE = true ;
答案 0 :(得分:0)
我在查询中进行了一些修改,并使用索引进行了扩展。
您的查询中的更改:
not exists...
,甚至可以检查是否t1.alert_id is null
order by
并基于rownum
s过滤
select r.*
from (
select t0.risk , t3.amount, t3.date_time , t0.id,
row_number() over (
order by t0.risk desc, t3.amount desc, t3.date_time desc, t0.id desc) rnum
from reaction_alert t0
left join reaction_investigation t1 on t1.alert_id = t0.id
left join reaction_classification_type t2 on t2.id = t1.classification_type_id
join reaction_trans t3 on t3.id = t0.transaction_id
left join reaction_fraud_type t4 on t4.id = t1.fraud_type_id
left join reaction_card t5 on t5.hpan = t3.hpan
where
(
t1.alert_id is null -- <- this should be enough to replace "group by query"
or t1.classification_type_id is null
or t2.classification_type = 2
)
and t0.module_type = 0 and t0.processing_mode_type = 1
and t0.iss_inst in (1201, 1101)
) r
where 100 < rnum and rnum <= 120
order by rnum
此查询可能需要一些修改,如果没有数据访问,我无法检查一切是否正确。 语法没问题,我在包含查询中提到的列的样本表上运行它。 请检查您的查询和我的查询计数(当然删除rnum上的过滤器)。如果您发现任何逻辑错误,请更正。
<强>索引强>
没有数据访问很难说,但是连接中使用的列显然是候选者。 您可能在该字段上有索引,但它们似乎是主键或外键。 无论如何,我试试这些:
/* t0 */ create index idx_ra_cmplx1 on reaction_alert (module_type, processing_mode_type, iss_inst);
/* t1 */ create index idx_ri_alert_id on reaction_investigation (alert_id);
/* t2 */ create index idx_rct_id on reaction_classification_type (id);
/* t3 */ create index idx_rt_id on reaction_trans (id);
/* t3 */ create index idx_rt_cmplx1 on reaction_trans (id, amount desc, date_time desc);
/* t4 */ create index idx_rft_id on reaction_fraud_type (id);
/* t5 */ create index idx_rc_hpan on reaction_card (hpan);
下面是我如何构建表来测试查询。不太重要,但可能对某人有用。
create table reaction_alert (id number, transaction_id number, risk number, module_type number, processing_mode_type number, iss_inst number)
create table reaction_investigation (alert_id number, classification_type_id number, fraud_type_id number);
create table reaction_classification_type (id number, classification_type number);
create table reaction_trans (id number, amount number, hpan number, date_time date);
create table reaction_fraud_type (id number);
create table reaction_card (hpan number);