您的位置:首页 > 其它

UPDATE多表关联更新时为什么会慢

2013-11-09 15:34 232 查看
构建环境如下:

Connected to Oracle Database 11g Enterprise Edition Release 11.2.0.1.0
Connected as test@192.168.1.118:1521/orcl

SQL> CREATE TABLE test1 AS SELECT * FROM Dba_Objects;
Table created
SQL> CREATE TABLE test2 AS SELECT * FROM Dba_Objects;
Table created
SQL> CREATE TABLE test3 AS SELECT * FROM Dba_Objects;
Table created
SQL> ALTER TABLE test2 ADD CONSTRAINTS pk_test2 PRIMARY KEY (object_id);
Table altered
SQL> ALTER TABLE test3 ADD CONSTRAINTS pk_test3 PRIMARY KEY (object_id);
Table altered


我们先来看一个查询的plan
SQL> explain plan FOR SELECT a.object_name,
2         (SELECT b.object_name FROM test2 b WHERE b.object_id = a.object_id) AS new_name,
3         a.object_type,
4         (SELECT c.object_name FROM test3 c WHERE c.object_id = a.object_id) AS new_type
5    FROM test1 a
6   WHERE EXISTS (SELECT NULL FROM test2 b WHERE b.object_id = a.object_id)
7     AND EXISTS
8   (SELECT NULL FROM test3 c WHERE c.object_id = a.object_id);
Explained

SQL> select * from table(dbms_xplan.display());
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 2412657849
--------------------------------------------------------------------------------
| Id  | Operation                   | Name     | Rows  | Bytes | Cost (%CPU)| Ti
--------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |          | 56357 |  6384K|   326  (12)| 00
|   1 |  TABLE ACCESS BY INDEX ROWID| TEST2    |     1 |    79 |     2   (0)| 00
|*  2 |   INDEX UNIQUE SCAN         | PK_TEST2 |     1 |       |     1   (0)| 00
|   3 |  TABLE ACCESS BY INDEX ROWID| TEST3    |     1 |    79 |     2   (0)| 00
|*  4 |   INDEX UNIQUE SCAN         | PK_TEST3 |     1 |       |     1   (0)| 00
|   5 |  NESTED LOOPS SEMI          |          | 56357 |  6384K|   326  (12)| 00
|   6 |   NESTED LOOPS SEMI         |          | 59647 |  5999K|   312   (8)| 00
|   7 |    TABLE ACCESS FULL        | TEST1    | 80164 |  7045K|   293   (2)| 00
|*  8 |    INDEX UNIQUE SCAN        | PK_TEST3 | 44380 |   563K|     0   (0)| 00
|*  9 |   INDEX UNIQUE SCAN         | PK_TEST2 | 71566 |   908K|     0   (0)| 00
--------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
2 - access("B"."OBJECT_ID"=:B1)
4 - access("C"."OBJECT_ID"=:B1)
8 - access("C"."OBJECT_ID"="A"."OBJECT_ID")
9 - access("B"."OBJECT_ID"="A"."OBJECT_ID")
Note
-----
- dynamic sampling used for this statement (level=2)
28 rows selected

注意ID=1、2、3、4这几行PLAN。对应的分别就是

(SELECT b.object_name FROM test2 b WHERE b.object_id = a.object_id) AS new_name,

(SELECT c.object_name FROM test3 c WHERE c.object_id = a.object_id) AS new_type

两个语句

下面是一个UPDATE的PLAN

SQL> explain plan for UPDATE test1 a
2     SET a.object_name =
3         (SELECT b.object_name FROM test2 b WHERE b.object_id = a.object_id),
4         a.object_type =
5         (SELECT c.object_type FROM test3 c WHERE c.object_id = a.object_id)
6   WHERE EXISTS (SELECT NULL FROM test2 b WHERE b.object_id = a.object_id)
7     AND EXISTS
8   (SELECT NULL FROM test3 c WHERE c.object_id = a.object_id);
Explained

SQL> select * from table(dbms_xplan.display());
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 2604142680
--------------------------------------------------------------------------------
| Id  | Operation                    | Name     | Rows  | Bytes | Cost (%CPU)| T
--------------------------------------------------------------------------------
|   0 | UPDATE STATEMENT             |          | 56357 |  6384K|   338K (34)| 0
|   1 |  UPDATE                      | TEST1    |       |       |            |
|   2 |   NESTED LOOPS SEMI          |          | 56357 |  6384K|   326  (12)| 0
|   3 |    NESTED LOOPS SEMI         |          | 59647 |  5999K|   312   (8)| 0
|   4 |     TABLE ACCESS FULL        | TEST1    | 80164 |  7045K|   293   (2)| 0
|*  5 |     INDEX UNIQUE SCAN        | PK_TEST3 | 44380 |   563K|     0   (0)| 0
|*  6 |    INDEX UNIQUE SCAN         | PK_TEST2 | 71566 |   908K|     0   (0)| 0
|   7 |   TABLE ACCESS BY INDEX ROWID| TEST2    |     1 |    79 |     2   (0)| 0
|*  8 |    INDEX UNIQUE SCAN         | PK_TEST2 |     1 |       |     1   (0)| 0
|   9 |   TABLE ACCESS BY INDEX ROWID| TEST3    |     1 |    24 |     2   (0)| 0
|* 10 |    INDEX UNIQUE SCAN         | PK_TEST3 |     1 |       |     1   (0)| 0
--------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
5 - access("C"."OBJECT_ID"="A"."OBJECT_ID")
6 - access("B"."OBJECT_ID"="A"."OBJECT_ID")
8 - access("B"."OBJECT_ID"=:B1)
10 - access("C"."OBJECT_ID"=:B1)
Note
-----
- dynamic sampling used for this statement (level=2)
29 rows selected

注意这儿的ID=7、8、9、10

对应的分别就是

a.object_name = (SELECT b.object_name FROM test2 b WHERE b.object_id = a.object_id),

a.object_type = (SELECT c.object_type FROM test3 c WHERE c.object_id = a.object_id)

大家仔细对比这两个语句,看下UPDATE的多表关联更新是不是与标量子查询很象。

那么标题量子查询慢的时候,对应的UPDATE慢也就不稀奇了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: