Sql 查询优化-左联接中的子选择
我正在优化一个sql查询,发现一行代码似乎在破坏我的查询性能:Sql 查询优化-左联接中的子选择,sql,oracle,Sql,Oracle,我正在优化一个sql查询,发现一行代码似乎在破坏我的查询性能: LEFT JOIN anothertable lastweek AND lastweek.date>= (SELECT MAX(table.date)-7 max_date_lweek FROM table table WHERE table.id= lastweek.id) AND last
LEFT JOIN anothertable lastweek
AND lastweek.date>= (SELECT MAX(table.date)-7 max_date_lweek
FROM table table
WHERE table.id= lastweek.id)
AND lastweek.date< (SELECT MAX(table.date) max_date_lweek
FROM table table
WHERE table.id= lastweek.id)
我正在研究一种优化这些线路的方法,但我被难倒了。如果有人有任何想法,请告诉我
-----------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost | Time |
-----------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1908654 | 145057704 | 720461 | 00:00:29 |
| * 1 | HASH JOIN RIGHT OUTER | | 1908654 | 145057704 | 720461 | 00:00:29 |
| 2 | VIEW | VW_DCL_880D8DA3 | 427487 | 7694766 | 716616 | 00:00:28 |
| * 3 | HASH JOIN | | 427487 | 39328804 | 716616 | 00:00:28 |
| 4 | VIEW | VW_SQ_2 | 7174144 | 193701888 | 278845 | 00:00:11 |
| 5 | HASH GROUP BY | | 7174144 | 294139904 | 278845 | 00:00:11 |
| 6 | TABLE ACCESS STORAGE FULL | TASK | 170994691 | 7010782331 | 65987 | 00:00:03 |
| * 7 | HASH JOIN | | 8549735 | 555732775 | 429294 | 00:00:17 |
| 8 | VIEW | VW_SQ_1 | 7174144 | 172179456 | 278845 | 00:00:11 |
| 9 | HASH GROUP BY | | 7174144 | 294139904 | 278845 | 00:00:11 |
| 10 | TABLE ACCESS STORAGE FULL | TASK | 170994691 | 7010782331 | 65987 | 00:00:03 |
| 11 | TABLE ACCESS STORAGE FULL | TASK | 170994691 | 7010782331 | 65987 | 00:00:03 |
| * 12 | TABLE ACCESS STORAGE FULL | TASK | 1908654 | 110701932 | 2520 | 00:00:01 |
-----------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
------------------------------------------
* 1 - access("SYS_ID"(+)="TASK"."PARENT")
* 3 - access("ITEM_2"="TASK_LWEEK"."SYS_ID")
* 3 - filter("TASK_LWEEK"."SNAPSHOT_DATE"<"MAX_DATE_LWEEK")
* 7 - access("ITEM_1"="TASK_LWEEK"."SYS_ID")
* 7 - filter("TASK_LWEEK"."SNAPSHOT_DATE">=INTERNAL_FUNCTION("MAX_DATE_LWEEK"))
* 12 - storage("TASK"."CLOSED_AT" IS NULL OR "TASK"."CLOSED_AT">=TRUNC(SYSDATE@!)-15)
* 12 - filter("TASK"."CLOSED_AT" IS NULL OR "TASK"."CLOSED_AT">=TRUNC(SYSDATE@!)-15)
由于没有完整的信息,我建议: 您使用同一查询两次,那么为什么不使用CTE,例如
with CTE_example as (SELECT MAX(table.date), max_date_lweek, ID
FROM table table)
好吧,你甚至没有显示选择。正如我所看到的,select是在Exadata表访问存储已满的情况下完成的,也许您需要问问自己,为什么需要对同一个表进行4次访问 根据对CBO的估计,第四次访问主表任务的第6、10、11、12行,共有170994691行。我不知道这些统计数据是最新的,还是由于缺乏良好的统计数据而优化了抽样 可以使用解决方案生成大纲查询中多次需要的中间结果
with my_set as
(SELECT MAX(table.date)-7 max_date_lweek ,
max(table.date) as max_date,
id from FROM table )
select
.......................
from ...
left join anothertable lastweek on ( ........ )
left join myset on ( anothertable.id = myset.id )
where
lastweek.date >= myset.max_date_lweek
and
lastweek.date < myset.max_date
请考虑到您没有提供查询,所以我猜了很多事情。查看您的解释计划,唯一被访问的表是TASK。由此,我推断您的示例中的表:另一个表和表实际上是同一个表,因此,您试图获取该表中存在的每个id值的最后一周数据 如果所有这些都是真的,那么使用分析函数来获取每个id的最大日期值,然后基于该值进行限制应该会快得多 这是我的意思的一个例子。注:我使用dte而不是date,以消除与保留字date的混淆
LEFT JOIN ( SELECT lastweek.*,
max(dte) OVER ( PARTITION BY id ) max_date
FROM anothertable lastweek ) lastweek
ON 1=1 -- whatever other join conditions you have, seemingly omitted from your post
AND lastweek.dte >= lastweek.max_date - 7;
同样,只有当我正确地认为表和另一个表实际上是同一个表时,这才有效。我建议您创建一个小查询来演示您的问题,并显示所有相关表中的示例数据。是否运行解释计划并发布结果?是否可以放置整个查询和解释计划?发布的信息不足-可能使用WITH子句封装该日期逻辑-使用这些嵌套视图也可能不太好..您的左连接没有使用ON关键字。上周参加什么活动?我不确定是否缺少ON有效,您可以尝试添加它,看看它是否有不同。