不同表的复合索引 ORACLE SQL
Composite index on different tables ORACLE SQL
大家好,我需要优化这个查询:
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;
但是我如何在按列排列的所有顺序上使用索引 (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);
但这也无济于事(
P.S。列 ALERT.RISK, TRANS.AMOUNT , TRANS.DATE_TIME
具有 NULLABLE = true;
我在查询中做了一些修改,并用索引进行了实验。
您查询的变化:
- 用 ansi 连接替换旧式连接
- 似乎内部查询计数行可以替换为
not exists...
甚至检查 t1.alert_id is null
- 添加了解析 row_number 函数而不是
order by
和基于 rownum
s 的过滤器
- 我不确定是否需要与 t4 和 t5 的连接 - 如果这些表存在 1 到许多的关系,那么它们是,但如果一个到
那么这些表对结果没有影响(来自 t4 和
t5 不用于条件和顺序)
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);
大家好,我需要优化这个查询:
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;
但是我如何在按列排列的所有顺序上使用索引 (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);
但这也无济于事(
P.S。列 ALERT.RISK, TRANS.AMOUNT , TRANS.DATE_TIME
具有 NULLABLE = true;
我在查询中做了一些修改,并用索引进行了实验。
您查询的变化:
- 用 ansi 连接替换旧式连接
- 似乎内部查询计数行可以替换为
not exists...
甚至检查t1.alert_id is null
- 添加了解析 row_number 函数而不是
order by
和基于rownum
s 的过滤器
- 我不确定是否需要与 t4 和 t5 的连接 - 如果这些表存在 1 到许多的关系,那么它们是,但如果一个到 那么这些表对结果没有影响(来自 t4 和 t5 不用于条件和顺序)
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);