预测推入组中每个用户的最大和最小统计数据时出现问题
我在 ORACLE 10g DB 中有两个表:
表 USERS 包含列: 用户 ID |组ID |其他细节 其中每个用户有 1 条记录,总共 400 条,每个组中有大约 1-10 个用户。
以及表 USAGE 的列: 用户 ID |日期 |数量 其中每个用户有 10000 行。 (所以400 * 10000行)
我有用户表在UserId,GroupId和(UserId,GroupId)上索引,表使用情况在(UserId,Date)上索引
我想查看每个用户的最大和总使用量给定的组。 像这样的事情:
select User.UserId, maxAmount, Total from
Users
JOIN
( select UserId,max(Amount) as maxAmount from USAGE group by UserId ) A
ON User.UserId = A.UserId
JOIN
( select UserId,min(Amount) as minAmount from USAGE group by UserId ) B
ON User.UserId = B.UserId
WHERE User.GroupId = 'some_group_id'
但是它非常慢(大约20秒),但是当我单独做它们时(只是最大和最小,但不是同时),就像这样:
select User.UserId, maxAmount, minAmount from
Users
JOIN
( select UserId,max(Amount) as maxAmount from USAGE group by UserId ) A
ON User.UserId = A.UserId
WHERE User.GroupId = 'some_group_id'
它在一瞬间运行!
我可以非常快地单独加入它们,但是当我将它们全部加入时,速度非常慢,这是没有意义的。
以下是计划,其中我将前面的语句中的内联视图创建为实际视图:
create view usage_min as select user_id, min(amount) from usage group by user_id;
create view usage_max as select user_id, max(amount) from usage group by user_id;
explain plan for select * from usage_min join users using(user_id) where group_id='1212882339';
select * from table(dbms_xplan.display);
Plan hash value: 3874246446
-----------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-----------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 139 | 1162 (1)| 00:00:14 |
| 1 | HASH GROUP BY | | 1 | 139 | 1162 (1)| 00:00:14 |
| 2 | TABLE ACCESS BY INDEX ROWID | USAGE | 7977 | 116K| 1157 (1)| 00:00:14 |
| 3 | NESTED LOOPS | | 11085 | 1504K| 1160 (1)| 00:00:14 |
| 4 | MAT_VIEW ACCESS BY INDEX ROWID| USERS | 1 | 124 | 3 (0)| 00:00:01 |
|* 5 | INDEX RANGE SCAN | USERS_KT | 1 | | 1 (0)| 00:00:01 |
|* 6 | INDEX RANGE SCAN | SYS_C0099818 | 7977 | | 79 (0)| 00:00:01 |
-----------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
5 - access("USERS"."group_id"='1212882339')
6 - access("user_id"="USERS"."user_id")
explain plan for select * from users join usage_max using(user_id) where group_id='1212882339';
select * from table(dbms_xplan.display);
Plan hash value: 2384977958
-----------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-----------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 145 | 519 (2)| 00:00:07 |
| 1 | HASH GROUP BY | | 1 | 145 | 519 (2)| 00:00:07 |
| 2 | TABLE ACCESS BY INDEX ROWID | USAGE2 | 18251 | 374K| 512 (1)| 00:00:07 |
| 3 | NESTED LOOPS | | 25362 | 3591K| 515 (1)| 00:00:07 |
| 4 | MAT_VIEW ACCESS BY INDEX ROWID| USERS | 1 | 124 | 3 (0)| 00:00:01 |
|* 5 | INDEX RANGE SCAN | USERS_KT | 1 | | 1 (0)| 00:00:01 |
|* 6 | INDEX RANGE SCAN | T2_user_id | 18251 | | 25 (4)| 00:00:01 |
-----------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
5 - access("USERS"."group_id"='1212882339')
6 - access("USERS"."user_id"="user_id")
explain plan for select * from users join usage_max using(user_id) join usage_min using(user_id) where group_id='1212882339';
select * from table(dbms_xplan.display);
Plan hash value: 3190011991
-----------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-----------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 100 | 16600 | 6782 (19)| 00:01:22 |
|* 1 | HASH JOIN | | 100 | 16600 | 6782 (19)| 00:01:22 |
| 2 | MERGE JOIN | | 100 | 14500 | 3176 (19)| 00:00:39 |
| 3 | SORT JOIN | | 2920K| 58M| 3172 (19)| 00:00:39 |
| 4 | VIEW | USAGE_MAX | 2920K| 58M| 3172 (19)| 00:00:39 |
| 5 | HASH GROUP BY | | 2920K| 58M| 3172 (19)| 00:00:39 |
| 6 | TABLE ACCESS FULL | USAGE2 | 2920K| 58M| 2686 (5)| 00:00:33 |
|* 7 | SORT JOIN | | 1 | 124 | 4 (25)| 00:00:01 |
| 8 | MAT_VIEW ACCESS BY INDEX ROWID| USERS | 1 | 124 | 3 (0)| 00:00:01 |
|* 9 | INDEX RANGE SCAN | USERS_KT | 1 | | 1 (0)| 00:00:01 |
| 10 | VIEW | USAGE_MIN | 398 | 8358 | 3605 (19)| 00:00:44 |
| 11 | HASH GROUP BY | | 398 | 5970 | 3605 (19)| 00:00:44 |
| 12 | TABLE ACCESS FULL | USAGE | 3174K| 45M| 3073 (4)| 00:00:37 |
-----------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - access("USAGE_MAX"."user_id"="USAGE_MIN"."user_id")
7 - access("USERS"."user_id"="USAGE_MAX"."user_id")
filter("USERS"."user_id"="USAGE_MAX"."user_id")
9 - access("USERS"."group_id"='1212882339')
I have two tables in an ORACLE 10g DB:
The table USERS with columns:
UserId | GroupId | Other details
where there's 1 record for each User, total 400, and there c.a. 1-10 users in each Group.
and the table USAGE with columns:
UserId | Date | Amount
where there's 10000 rows for each user. (so 400*10000 rows)
I have the Users table indexed on UserId, GroupId and (UserId,GroupId) and the table Usage is indexed on (UserId,Date)
I want to see the Max and Total amount of usage for each user in a given group.
Something like this:
select User.UserId, maxAmount, Total from
Users
JOIN
( select UserId,max(Amount) as maxAmount from USAGE group by UserId ) A
ON User.UserId = A.UserId
JOIN
( select UserId,min(Amount) as minAmount from USAGE group by UserId ) B
ON User.UserId = B.UserId
WHERE User.GroupId = 'some_group_id'
But it is very slow (approx 20 sec), but when I do them separately (just Max and just Min, but not both at once), like this:
select User.UserId, maxAmount, minAmount from
Users
JOIN
( select UserId,max(Amount) as maxAmount from USAGE group by UserId ) A
ON User.UserId = A.UserId
WHERE User.GroupId = 'some_group_id'
it runs in a flash!
It just makes no sense that I can join them separately very fast, but when I join them all three it's very slow.
Here are the plans, where I created the inline views in the preceeding statements as actual views:
create view usage_min as select user_id, min(amount) from usage group by user_id;
create view usage_max as select user_id, max(amount) from usage group by user_id;
explain plan for select * from usage_min join users using(user_id) where group_id='1212882339';
select * from table(dbms_xplan.display);
Plan hash value: 3874246446
-----------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-----------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 139 | 1162 (1)| 00:00:14 |
| 1 | HASH GROUP BY | | 1 | 139 | 1162 (1)| 00:00:14 |
| 2 | TABLE ACCESS BY INDEX ROWID | USAGE | 7977 | 116K| 1157 (1)| 00:00:14 |
| 3 | NESTED LOOPS | | 11085 | 1504K| 1160 (1)| 00:00:14 |
| 4 | MAT_VIEW ACCESS BY INDEX ROWID| USERS | 1 | 124 | 3 (0)| 00:00:01 |
|* 5 | INDEX RANGE SCAN | USERS_KT | 1 | | 1 (0)| 00:00:01 |
|* 6 | INDEX RANGE SCAN | SYS_C0099818 | 7977 | | 79 (0)| 00:00:01 |
-----------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
5 - access("USERS"."group_id"='1212882339')
6 - access("user_id"="USERS"."user_id")
explain plan for select * from users join usage_max using(user_id) where group_id='1212882339';
select * from table(dbms_xplan.display);
Plan hash value: 2384977958
-----------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-----------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 145 | 519 (2)| 00:00:07 |
| 1 | HASH GROUP BY | | 1 | 145 | 519 (2)| 00:00:07 |
| 2 | TABLE ACCESS BY INDEX ROWID | USAGE2 | 18251 | 374K| 512 (1)| 00:00:07 |
| 3 | NESTED LOOPS | | 25362 | 3591K| 515 (1)| 00:00:07 |
| 4 | MAT_VIEW ACCESS BY INDEX ROWID| USERS | 1 | 124 | 3 (0)| 00:00:01 |
|* 5 | INDEX RANGE SCAN | USERS_KT | 1 | | 1 (0)| 00:00:01 |
|* 6 | INDEX RANGE SCAN | T2_user_id | 18251 | | 25 (4)| 00:00:01 |
-----------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
5 - access("USERS"."group_id"='1212882339')
6 - access("USERS"."user_id"="user_id")
explain plan for select * from users join usage_max using(user_id) join usage_min using(user_id) where group_id='1212882339';
select * from table(dbms_xplan.display);
Plan hash value: 3190011991
-----------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-----------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 100 | 16600 | 6782 (19)| 00:01:22 |
|* 1 | HASH JOIN | | 100 | 16600 | 6782 (19)| 00:01:22 |
| 2 | MERGE JOIN | | 100 | 14500 | 3176 (19)| 00:00:39 |
| 3 | SORT JOIN | | 2920K| 58M| 3172 (19)| 00:00:39 |
| 4 | VIEW | USAGE_MAX | 2920K| 58M| 3172 (19)| 00:00:39 |
| 5 | HASH GROUP BY | | 2920K| 58M| 3172 (19)| 00:00:39 |
| 6 | TABLE ACCESS FULL | USAGE2 | 2920K| 58M| 2686 (5)| 00:00:33 |
|* 7 | SORT JOIN | | 1 | 124 | 4 (25)| 00:00:01 |
| 8 | MAT_VIEW ACCESS BY INDEX ROWID| USERS | 1 | 124 | 3 (0)| 00:00:01 |
|* 9 | INDEX RANGE SCAN | USERS_KT | 1 | | 1 (0)| 00:00:01 |
| 10 | VIEW | USAGE_MIN | 398 | 8358 | 3605 (19)| 00:00:44 |
| 11 | HASH GROUP BY | | 398 | 5970 | 3605 (19)| 00:00:44 |
| 12 | TABLE ACCESS FULL | USAGE | 3174K| 45M| 3073 (4)| 00:00:37 |
-----------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - access("USAGE_MAX"."user_id"="USAGE_MIN"."user_id")
7 - access("USERS"."user_id"="USAGE_MAX"."user_id")
filter("USERS"."user_id"="USAGE_MAX"."user_id")
9 - access("USERS"."group_id"='1212882339')
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
至少,我想使用类似
或更简单的方法来访问
USAGE
表一次At a minimum, I'd want to hit the
USAGE
table just once using something likeor even more simply