問題

2011-08-11 8 views
0

私はORACLE 10グラムDB内の2つのテーブルがあります:列の問題

テーブルUSERS: ユーザーIDを| GroupId |その他の詳細 各ユーザーごとに1レコードあり、合計400、そこにはc.aがあります。各グループのユーザー数は1〜10人です。

と表USAGEの列: UserId |日付|金額 各ユーザーに10000の行があります。 (その400 * 10000行)

は、私は、ユーザーテーブルはユーザーID、グループID、および(ユーザーID、グループID)にインデックスされていると、テーブルの使用は、(ユーザーID、日付)にインデックスされ

は、私はマックスを見たいと特定のグループ内の各ユーザーの使用量の合計。このような 何か:

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秒)ですが、私はそれらを個別に行うとき(ちょうどMaxとちょうど分、一度に両方はできません):

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' 

これはフラッシュで実行されます!

私はそれらを非常に速く別々に参加させることはできませんが、3つすべてに参加すると非常に遅いです。ここで

は、私が実際のビューなどの先行文でインライン・ビューを作成した計画、以下のとおりです。

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') 

答えて

1
  • 問い合わせ計画は何ですか?
  • 最初の行を取得する時間を測定していますか?または、最後の行を取得する時間を測定していますか?最低で

、私は

select User.UserId, maxAmount, Total from 
Users 
JOIN 
(select UserId, 
     max(Amount) as maxAmount, 
     sum(Amount) as Total 
    from USAGE group by UserId) A 
ON User.UserId = A.UserId 
WHERE User.GroupId = 'some_group_id' 

またはそれ以上単に

SELECT user.userId, 
     max(usage.Amount) maxAmount, 
     sum(usage.Amount) total 
    FROM user 
     join usage on (user.userId = usage.userId) 
WHERE user.GroupId = 'some_group_id' 
GROUP BY user.userId 
+0

申し訳ありませんが、私の問題は、別の簡易版であるようなものを使用して一度だけUSAGEテーブルをヒットにしたいと思います集計演算子が行の同じサブセットで作業していないセットアップ。 (だから私は2つの別々のヒットでそれを行う必要があります)。問題は、同じクエリで両方を行うと、述語を集約インラインビューにプッシュしないということです。 – related

+1

@Eirikur - 解決しようとしている問題を示す例を投稿できますか?述語がプッシュされていないことを示すプランを投稿できますか? 2つの集計を取得するために2回スキャンするのではなく、分析関数を使用してテーブルを1回ヒットできますか? –

+0

デモンストレーションについては、編集された質問を参照してください。私はインラインビューを実際のビューに置き換えましたが、それは問題ではありません。 – related