sql - Oracle 查询中避免更新字段的最佳方法是什么(如果未更改)?

标签 sql oracle sql-update

我只是想知道我可以在 Oracle 查询中使用的最佳方法,以避免更新未更改的字段?

Update xtab1 set xfield1='xxx' where xkey='123';

在性能方面,如果 xfield1 的现有值为“xxx”,则不应调用此更新的最佳方式是什么。

选项 1:

  • step1:Invoke a SELECT to Fetch the value of xfield1
  • step2:If the above value is not 'xxx', then only invoke UPDATE

选项 2:

  • Invoke update as below:

    Update xtab1 set xfield1='xxx' where xkey='123' and xfield1 <> 'xxx'

请让我知道以上两种方法中哪一种是最佳和理想的方法,或者是否有其他理想的方法可以使用?

感谢您的帮助

最佳答案

Update xtab1 set xfield1='xxx' where xkey='123' and xfield1 <> 'xxx'

过滤谓词 在进行更新之前应用。因此,我会选择选项 2,让 Oracle 为您完成这项工作,而不是手动执行以首先过滤掉行。此外,在两个不同的步骤中执行此操作将是一项开销。行的过滤应该是同一步骤的一部分。

关于性能,我认为索引会发挥重要作用。

你可以测试一下看看:

没有索引

选项 1

SQL> EXPLAIN PLAN FOR
  2  UPDATE t SET sal = 9999 WHERE deptno = 20;

Explained.

SQL>
SQL> SELECT * FROM TABLE(dbms_xplan.display);

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 931696821

---------------------------------------------------------------------------
| Id  | Operation          | Name | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------
|   0 | UPDATE STATEMENT   |      |     5 |    35 |     3   (0)| 00:00:01 |
|   1 |  UPDATE            | T    |       |       |            |          |
|*  2 |   TABLE ACCESS FULL| T    |     5 |    35 |     3   (0)| 00:00:01 |
---------------------------------------------------------------------------

Predicate Information (identified by operation id):

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
---------------------------------------------------

   2 - filter("DEPTNO"=20)

14 rows selected.

SQL>

选项 2

SQL> EXPLAIN PLAN FOR
  2  UPDATE t SET sal = 9999 WHERE deptno = 20 AND sal<>9999;

Explained.

SQL>
SQL> SELECT * FROM TABLE(dbms_xplan.display);

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 931696821

---------------------------------------------------------------------------
| Id  | Operation          | Name | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------
|   0 | UPDATE STATEMENT   |      |     4 |    28 |     3   (0)| 00:00:01 |
|   1 |  UPDATE            | T    |       |       |            |          |
|*  2 |   TABLE ACCESS FULL| T    |     4 |    28 |     3   (0)| 00:00:01 |
---------------------------------------------------------------------------

Predicate Information (identified by operation id):

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
---------------------------------------------------

   2 - filter("DEPTNO"=20 AND "SAL"<>9999)

14 rows selected.

有索引

SQL> CREATE INDEX t_idx ON t(deptno,sal);

Index created.

选项 1

SQL> EXPLAIN PLAN FOR
  2  UPDATE t SET sal = 9999 WHERE deptno = 20;

Explained.

SQL>
SQL> SELECT * FROM TABLE(dbms_xplan.display);

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 1175576152

---------------------------------------------------------------------------
| Id  | Operation         | Name  | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------
|   0 | UPDATE STATEMENT  |       |     5 |    35 |     1   (0)| 00:00:01 |
|   1 |  UPDATE           | T     |       |       |            |          |
|*  2 |   INDEX RANGE SCAN| T_IDX |     5 |    35 |     1   (0)| 00:00:01 |
---------------------------------------------------------------------------

Predicate Information (identified by operation id):

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
---------------------------------------------------

   2 - access("DEPTNO"=20)

14 rows selected.

SQL>

选项 2

SQL> EXPLAIN PLAN FOR
  2  UPDATE t SET sal = 9999 WHERE deptno = 20 AND sal<>9999;

Explained.

SQL>
SQL> SELECT * FROM TABLE(dbms_xplan.display);

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 1175576152

---------------------------------------------------------------------------
| Id  | Operation         | Name  | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------
|   0 | UPDATE STATEMENT  |       |     4 |    28 |     1   (0)| 00:00:01 |
|   1 |  UPDATE           | T     |       |       |            |          |
|*  2 |   INDEX RANGE SCAN| T_IDX |     4 |    28 |     1   (0)| 00:00:01 |
---------------------------------------------------------------------------

Predicate Information (identified by operation id):

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
---------------------------------------------------

   2 - access("DEPTNO"=20)
       filter("SAL"<>9999)

15 rows selected.

SQL>

因此,在所有情况下,在选项 2 中,应用过滤器("SAL"<>9999)

关于sql - Oracle 查询中避免更新字段的最佳方法是什么(如果未更改)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29619786/

相关文章:

python - PostgreSQL ALTER SEQUENCE 在 django 中使用 psycopg2

c++ - 获取 typedef 结构数组中的行

sql - 计算sqlite中特征的出现

java - 从 Oracle 函数调用 Java 函数

sql - 序列不存在 ORA-02289

mysql - 基于其他列sql更新列的表达式

对于没有记录的日期,MySQL 显示计数为 0

java - 如何获取一段时间内特定日期的出现情况

MySQL 更新查询

mysql - 一周中特定日期的 SQL 更新