[英]Oracle Query Optimization
I have the following tables 我有下表
Master Table 主表
id
----
1x
2x
.... ....
Assignment Table 作业表
id | type_id | assign_id
-----------------------------
1x | 2 | 554
1x | 3 | 664
2x | 2 | 919
2x | 4 | 514
Type table 型号表
type_id | create_date
----------------------
1 | 01/01/2009
2 | 01/01/2009
3 | 03/01/2009
4 | 04/01/2009
What i need for the query to output is something like this 我需要查询输出是这样的
id | max create_date type_id | assign_id
----------------------------------------------
1x | 3 | 664
2x | 4 | 514
Right now i'm doing something like this to acquire the results, but i'm sure there is a much better way to do this. 现在,我正在做类似的事情来获取结果,但是我敢肯定有更好的方法来做到这一点。
Q1
---
CREATE TABLE tmp_table as
SELECT m.id, max(t.create_date)
FROM master m, assignment a, type t
WHERE m.id=a.id
and a.type_id=t.type_id
GROUP BY m.id
Q2
--
SELECT tmp.id, a.type_id, a.assign_id
from tmp_table tmp, assignment a, type t
WHERE tmp.create_date=t.create_date
and t.type_id=a.type_id
Thanks for any help 谢谢你的帮助
No temp table necessary. 无需临时表。
select distinct
a.id,
first_value(t.type_id)
over (partition by a.id order by t.create_date desc)
as max_create_date_type_id,
first_value(a.assign_id)
over (partition by a.id order by t.create_date desc)
as assign_id
from assignment a, type t
where a.type_id = t.type_id
Using analytics, and then applying the DISTINCT operator is not the way to go, when you need to aggregate. 当您需要汇总时,使用分析方法然后应用DISTINCT运算符并不是可行的方法。
Here is a simpler and more performant version using only aggregates: 这是仅使用聚合的更简单,更高性能的版本:
SQL> select a.id
2 , max(t.type_id) keep (dense_rank last order by t.create_date) max_create_date_type_id
3 , max(a.assign_id) keep (dense_rank last order by t.create_date) assign_id
4 from assignment a
5 , type t
6 where a.type_id = t.type_id
7 group by a.id
8 /
ID MAX_CREATE_DATE_TYPE_ID ASSIGN_ID
-- ----------------------- ----------
1x 3 664
2x 4 514
2 rows selected.
And here is a test to prove it's more performant: 这是一个测试,以证明它的性能更高:
SQL> exec dbms_stats.gather_table_stats(user,'assignment')
PL/SQL procedure successfully completed.
SQL> exec dbms_stats.gather_table_stats(user,'type')
PL/SQL procedure successfully completed.
SQL> select /*+ gather_plan_statistics */
2 distinct
3 a.id,
4 first_value(t.type_id)
5 over (partition by a.id order by t.create_date desc)
6 as max_create_date_type_id,
7 first_value(a.assign_id)
8 over (partition by a.id order by t.create_date desc)
9 as assign_id
10 from assignment a, type t
11 where a.type_id = t.type_id
12 /
ID MAX_CREATE_DATE_TYPE_ID ASSIGN_ID
-- ----------------------- ----------
2x 4 514
1x 3 664
2 rows selected.
SQL> select * from table(dbms_xplan.display_cursor(null,null,'allstats last'))
2 /
PLAN_TABLE_OUTPUT
-------------------------------------------------------------------------------------------------------------------------
SQL_ID fu520w4kf2bbp, child number 0
-------------------------------------
select /*+ gather_plan_statistics */ distinct a.id,
first_value(t.type_id) over (partition by a.id order by
t.create_date desc) as max_create_date_type_id,
first_value(a.assign_id) over (partition by a.id order by
t.create_date desc) as assign_id from assignment a, type t where
a.type_id = t.type_id
Plan hash value: 4160194652
-------------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | OMem | 1Mem | Used-Mem |
-------------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 2 |00:00:00.01 | 6 | | | |
| 1 | HASH UNIQUE | | 1 | 4 | 2 |00:00:00.01 | 6 | 898K| 898K| 493K (0)|
| 2 | WINDOW SORT | | 1 | 4 | 4 |00:00:00.01 | 6 | 2048 | 2048 | 2048 (0)|
| 3 | WINDOW SORT | | 1 | 4 | 4 |00:00:00.01 | 6 | 2048 | 2048 | 2048 (0)|
|* 4 | HASH JOIN | | 1 | 4 | 4 |00:00:00.01 | 6 | 898K| 898K| 554K (0)|
| 5 | TABLE ACCESS FULL| ASSIGNMENT | 1 | 4 | 4 |00:00:00.01 | 3 | | | |
| 6 | TABLE ACCESS FULL| TYPE | 1 | 4 | 4 |00:00:00.01 | 3 | | | |
-------------------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
4 - access("A"."TYPE_ID"="T"."TYPE_ID")
28 rows selected.
SQL> select /*+ gather_plan_statistics */
2 a.id
3 , max(t.type_id) keep (dense_rank last order by t.create_date) max_create_date_type_id
4 , max(a.assign_id) keep (dense_rank last order by t.create_date) assign_id
5 from assignment a
6 , type t
7 where a.type_id = t.type_id
8 group by a.id
9 /
ID MAX_CREATE_DATE_TYPE_ID ASSIGN_ID
-- ----------------------- ----------
1x 3 664
2x 4 514
2 rows selected.
SQL> select * from table(dbms_xplan.display_cursor(null,null,'allstats last'))
2 /
PLAN_TABLE_OUTPUT
-------------------------------------------------------------------------------------------------------------------------
SQL_ID 156kpxgxmfjd3, child number 0
-------------------------------------
select /*+ gather_plan_statistics */ a.id , max(t.type_id)
keep (dense_rank last order by t.create_date) max_create_date_type_id
, max(a.assign_id) keep (dense_rank last order by t.create_date)
assign_id from assignment a , type t where a.type_id =
t.type_id group by a.id
Plan hash value: 3494156172
-----------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | OMem | 1Mem | Used-Mem |
-----------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 2 |00:00:00.01 | 6 | | | |
| 1 | SORT GROUP BY | | 1 | 2 | 2 |00:00:00.01 | 6 | 2048 | 2048 | 2048 (0)|
|* 2 | HASH JOIN | | 1 | 4 | 4 |00:00:00.01 | 6 | 898K| 898K| 594K (0)|
| 3 | TABLE ACCESS FULL| ASSIGNMENT | 1 | 4 | 4 |00:00:00.01 | 3 | | | |
| 4 | TABLE ACCESS FULL| TYPE | 1 | 4 | 4 |00:00:00.01 | 3 | | | |
-----------------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("A"."TYPE_ID"="T"."TYPE_ID")
25 rows selected.
As you can see, both are full scanning the tables and perform a hash join. 如您所见,两者都完全扫描了表并执行了哈希联接。 The difference is after this step.
区别在于此步骤之后。 The aggregate variant takes 4 rows and aggregates them to 2 rows with a SORT GROUP By.
聚合变量占用4行,并使用SORT GROUP By将其聚合为2行。 The analytic one is first sorting the 4-row-set twice and then applies a HASH UNIQUE to reduce the set to 2 rows.
分析人员首先对4行集排序两次,然后应用HASH UNIQUE将其减少为2行。
Regards, Rob. 问候,罗布。
If you are using Oracle9i release 2 or later, you can use the WITH clause. 如果使用的是Oracle9i 2版或更高版本,则可以使用WITH子句。 Then, instead of having to create a temp table Q1 and then running Q2, you could have one statement only.
然后,您不必只创建一个临时表Q1然后运行Q2,而只需一个语句。
Not only the syntax will be shorter, but this can also improve the query speed. 不仅语法会更短,而且还可以提高查询速度。
http://www.dba-oracle.com/t_with_clause.htm http://www.dba-oracle.com/t_with_clause.htm
Your query would become something like: 您的查询将变为:
WITH tmp_table as (
SELECT m.id, max(t.create_date)
FROM master m, assignment a, type t
WHERE m.id=a.id
and a.type_id=t.type_id
GROUP BY m.id )
SELECT tmp.id, a.type_id, a.assign_id
from tmp_table tmp, assignment a, type t
WHERE tmp.create_date=t.create_date
and t.type_id=a.type_id
you can use analytics to get the result in one query: 您可以使用分析功能在一个查询中获得结果:
SQL> WITH assignment_t AS (
2 SELECT '1x' ID, 2 type_id, 554 assign_id FROM dual UNION ALL
3 SELECT '1x', 3, 664 FROM dual UNION ALL
4 SELECT '2x', 2, 919 FROM dual UNION ALL
5 SELECT '2x', 4, 514 FROM dual
6 ), type_t AS (
7 SELECT 1 type_id, DATE '2009-01-01' create_date FROM dual UNION ALL
8 SELECT 2, DATE '2009-01-01' FROM dual UNION ALL
9 SELECT 3, DATE '2009-01-03' FROM dual UNION ALL
10 SELECT 4, DATE '2009-01-04' FROM dual
11 )
12 SELECT DISTINCT a.ID "id",
13 first_value(a.type_id)
14 OVER( PARTITION BY a.id
15 ORDER BY t.create_date DESC) "max create_date type_id",
16 first_value(a.assign_id)
17 OVER( PARTITION BY a.id
18 ORDER BY t.create_date DESC) "assign_id"
19 FROM assignment_t a
20 JOIN type_t t ON (a.type_id = t.type_id)
21 ;
id max create_date type_id assign_id
-- ----------------------- ----------
2x 4 514
1x 3 664
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.