Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/76.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 查询优化-左联接中的子选择_Sql_Oracle - Fatal编程技术网

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

我正在优化一个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 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有效,您可以尝试添加它,看看它是否有不同。