【问题标题】:need to tune this sql query to improve performance需要调整此 sql 查询以提高性能
【发布时间】:2015-09-16 18:48:56
【问题描述】:

我有以下查询。由于其中的子查询,这会降低性能。我尝试了很多来添加加入而不是子查询。但徒劳无功。谁能告诉我如何使用 JOIN 重写这个查询?

update Table_1
set status = 'Status_2' 
where status ='status_1' and (col_1, col_2, col_3, nvl(col_4,0), col_5) in ( 
               select col_1, col_2, col_3, nvl(col_4,0), col_5 from Table_2 where status ='Status_0');
    

请看下面的SELECT * FROM table(DBMS_XPLAN.Display);

Plan hash value: 1290346170
------------------------------------------------------------------------------------------------------
| Id  | Operation                     | Name                 | Rows  | Bytes | Cost (%CPU)| Time     |
------------------------------------------------------------------------------------------------------
|   0 | UPDATE STATEMENT              |                      |     1 |   376 |   456   (3)| 00:00:06 |
|   1 |  UPDATE                       | Table_1              |       |       |            |          |
|   2 |   NESTED LOOPS                |                      |       |       |            |          |
|   3 |    NESTED LOOPS               |                      |     1 |   376 |   456   (3)| 00:00:06 |
|   4 |     SORT UNIQUE               |                      |     1 |   316 |   454   (3)| 00:00:06 |
|*  5 |      TABLE ACCESS FULL        | Table_2              |     1 |   316 |   454   (3)| 00:00:06 |
|*  6 |     INDEX RANGE SCAN          | Table1_INDEX         |     1 |       |     1   (0)| 00:00:01 |
|*  7 |    TABLE ACCESS BY INDEX ROWID| Table_1              |     1 |    60 |     1   (0)| 00:00:01 |
------------------------------------------------------------------------------------------------------

【问题讨论】:

  • 请运行EXPLAIN PLAN FOR your_query,然后运行SELECT * FROM table(DBMS_XPLAN.Display),然后复制其输出并将其粘贴到问题中。
  • @kordirko,请看一下结果。
  • @Msn 估计时间只有6秒,相当快。查询实际花费的时间是多少?
  • 查询只查找 table2 中的 1 行,只更新 table1 中的 1 行,您想改进什么?这个计划是最优的。顺便说一句,您还没有向我们展示完整的解释计划,此表后面有一个谓词信息
  • 我认为你可以使用EXISTS instead of IN ;)。

标签: sql database oracle query-optimization sql-tuning


【解决方案1】:

如果你这样做,效果会更好吗?

update 
   (select Table_1.status
   from Table_1
      join Table_2 on 
             Table_1.col_1 = Table_2.col_1
         and Table_1.col_2 = Table_2.col_2
         and Table_1.col_3 = Table_2.col_3
         and nvl(Table_1.col_4, 0) = nvl(Table_2.col_4, 0)
         and Table_1.col_5 = Table_2.col_5
   where Table_1.status = 'status_1'
      and Table_2.status = 'Status_0')
set status = 'Status_2' ;

【讨论】:

  • 这是正确答案,但@Msn必须注意:如果(col_1, col_2, col_3, col_5)不包含Table_1和Table_2的主键那么Oracle会抛出ORA-01779错误(保留键的表)。
  • @Wernfried,收到错误“QL 错误:ORA-01779:无法修改映射到非键保留表的列”。我应该将所有这些字段都设为复合键吗?
【解决方案2】:

通过with 语句和Materialized 提示,您可以将table_2 的数据预加载到全局临时表中。这可能会提高您的查询性能。

【讨论】:

  • 我可以试试。我在手机上。使用 ASD as(select /*+materialized*/ col_1, col_2, col_3, nvl(col_4,0), col_5 from Table_2 where status ='Status_0') update Table_1 set status = 'Status_2' where status ='status_1' and ( col_1, col_2, col_3, nvl(col_4,0), col_5) in (select * from ASD)
  • 除非多次使用公用表表达式,否则使用未记录的具体化提示没有意义。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-02-26
  • 2019-03-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-06
相关资源
最近更新 更多