因此,oracle服务器上面的查询大约需要一个小时才能执行。 这是一种让它更快的方法吗?
SELECT *
FROM ACCOUNT_CYCLE_ACTIVITY aca1
WHERE aca1.ACTIVITY_TYPE_CODE='021'
AND aca1.ACTIVITY_GROUP_CODE='R12'
AND aca1.CYCLE_ACTIVITY_COUNT='999'
AND
EXISTS
(
SELECT 'a'
FROM ACCOUNT_CYCLE_ACTIVITY aca2
WHERE aca1.account_id = aca2.account_id
AND aca2.ACTIVITY_TYPE_CODE='021'
AND aca2.ACTIVITY_GROUP_CODE='R12'
AND aca2.CYCLE_ACTIVITY_COUNT ='1'
AND aca2.cycle_activity_amount > 25
AND (aca2.cycle_ctr > aca1.cycle_ctr)
AND aca2.cycle_ctr =
(
SELECT MIN(cycle_ctr)
FROM ACCOUNT_CYCLE_ACTIVITY aca3
WHERE aca3.account_id = aca1.account_id
AND aca3.ACTIVITY_TYPE_CODE='021'
AND aca3.ACTIVITY_GROUP_CODE='R12'
AND aca3.CYCLE_ACTIVITY_COUNT ='1'
)
);
所以基本上这就是它试图做的事情。 找到一个R12,021和999值的行, 对于所有这些行,我们必须确保存在具有相同帐户ID的另一行,但是R12,021和count = 1。 如果确实如此,我们必须确保该行的数量> 25,该行的cycle_ctr计数器最小。
正如您所看到的,我们在MIN(CYCLE_CTR)上进行选择时正在重复。
编辑:ACCOUNT_CYCLE_ACTIVITY表的列ACCOUNT_ID上有一个索引定义。
我们的表格为ACCOUNT_CYCLE_ACTIVITY。如果有一行ACTIVITY_TYPE_CODE ='021'且ACTIVITY_GROUP_CODE ='R12'且CYCLE_ACTIVITY_COUNT ='999',则代表标识行。
如果具有类似标识行的帐户具有其他021 R12行,则从标识行查询CYCLE_CTR值最小的行,该行大于CYCLE_CTR。如果找到一行,则找到的行的CYCLE_ACTIVITY_AMOUNT是> 25和CYCLE_ACTIVITY_COUNT = 1,报告帐户。
请注意,标识行仅用于标识,不会报告。
例如,这是一个应该报告的account_id上的SELECT。
Account_ID Group_Code Type_code Cycle_ctr Activity_Amount Activity_count
53116267 R12 021 14 0 999
53116267 R12 021 25 35 1
53116267 R12 021 22 35 1
53116267 R12 021 20 35 1
除了999和1之外,还有其他几个Activity_count,因此需要WHERE子句。
同样,如果上面的例子如下:
Account_ID Group_Code Type_code Cycle_ctr Activity_Amount Activity_count
53116267 R12 021 14 0 999
53116267 R12 021 25 35 1
53116267 R12 021 22 35 1
53116267 R12 021 20 **20** 1
它不会被报告,因为具有最低cycle_ctr的行的activity_amount大于标识行的cycle_ctr是20,小于25。
解释
之后的计划 explain plan for select * from account_activity;
select * from table(dbms_xplan.display);
Plan hash value: 1692077632
---------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop |
---------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 470M| 12G| 798K (1)| 02:39:38 | | |
| 1 | PARTITION HASH ALL | | 470M| 12G| 798K (1)| 02:39:38 | 1 | 64 |
| 2 | TABLE ACCESS STORAGE FULL| ACCOUNT_ACTIVITY | 470M| 12G| 798K (1)| 02:39:38 | 1 | 64 |
---------------------------------------------------------------------------------------------------------------
答案 0 :(得分:2)
我可能会首先使用WITH语句来希望减少选择数据的次数,并使其更具可读性。我建议的另一件事是通过某种联接替换存在。
with base as
(
select *
from account_cycle_activity
where activity_type_code = '021'
and activity_group_code = 'R12'
)
SELECT *
FROM base aca1
WHERE aca1.CYCLE_ACTIVITY_COUNT='999'
AND
EXISTS
(
SELECT 'a'
FROM base aca2
WHERE aca1.account_id = aca2.account_id
AND aca2.CYCLE_ACTIVITY_COUNT ='1'
AND aca2.cycle_activity_amount > 25
AND (aca2.cycle_ctr > aca1.cycle_ctr)
AND aca2.cycle_ctr =
(
SELECT MIN(cycle_ctr)
FROM base aca3
WHERE aca3.account_id = aca1.account_id
AND aca3.CYCLE_ACTIVITY_COUNT ='1'
)
);
答案 1 :(得分:1)
使用显式连接重写查询,而不是使用EXISTS重写。
基本上这两行
WHERE aca1.account_id = aca2.account_id
AND (aca2.cycle_ctr > aca1.cycle_ctr)
是加入第一个和第二个选择的连接条件,这个加入第一个和第三个。
WHERE aca3.account_id = aca1.account_id
查询应如下所示
select distinct aca1.*
FROM ACCOUNT_CYCLE_ACTIVITY aca1, ACCOUNT_CYCLE_ACTIVITY aca2, ACCOUNT_CYCLE_ACTIVITY aca3
WHERE
join conditions and other selection conditions
答案 2 :(得分:1)
我对查询的重写是这样的:
Select Aca1.*
From Account_Cycle_Activity Aca1
Join Account_Cycle_Activity Aca2
On Aca2.Account_Id = Aca1.Account_Id
And Aca2.Group_Code = Aca1.Group_Code
And Aca2.Type_Code = Aca1.Type_Code
And Aca2.Activity_Amount > 25
And Aca2.Activity_Count = 1
And Aca2.Cycle_Ctr > Aca1.Cycle_Ctr
And Aca2.Cycle_Ctr =(
Select Min( Cycle_Ctr )
From Account_Cycle_Activity Aca3
Where Aca3.Account_Id = Aca1.Account_Id
And Aca3.Type_Code = Aca1.Type_Code
And Aca3.Group_Code = Aca1.Group_Code
And Aca3.Activity_Count =1
)
Where Aca1.Type_Code = 21
And Aca1.Group_Code = 'R12'
And Aca1.Activity_Count = 999;
但是执行计划并没有那么不同,更重要的是,成本14是相同的。然而,然后我添加了两个索引,成本从14降到2.我试图创建一个小提琴,但像往常一样,Oracle部分不起作用。所以这就是:
Create Table Account_Cycle_Activity(
Account_Id Int Not Null,
Group_Code Char( 3 ) Not Null,
Type_Code Int Not Null,
Cycle_Ctr Int Not Null,
Activity_Amount Int Not Null,
Activity_Count Int Not Null
);
insert into Account_Cycle_Activity
select 53116267, 'R12', 21, 14, 0, 999 from dual union all
select 53116267, 'R12', 21, 25, 35, 1 from dual union all
Select 53116267, 'R12', 21, 22, 35, 1 From Dual Union All
select 53116267, 'R12', 21, 20, 35, 1 from dual;
-- Execute the query before creating these indexes and again after.
Create Index Ix_Account_Cycle_Activity1
On Account_Cycle_Activity( Account_Id, Group_Code, Type_Code, Activity_Amount, Activity_Count );
Create Index Ix_Account_Cycle_Activity2
On Account_Cycle_Activity( Cycle_Ctr );