UPDATE多表关联更新时为什么会慢
2013-11-09 15:34
232 查看
构建环境如下:
我们先来看一个查询的plan
注意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
注意这儿的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慢也就不稀奇了。
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慢也就不稀奇了。
相关文章推荐
- [转]oracle update set select from 关联更新
- Oracle多表关联更新(update多表关联)
- 用UPDATE SET FROM 语句来关联表更新数据
- Oracle关联更新语法(T-SQL中的update...from)
- Oracle 多表关联更新update
- mysql关联多表进行update更新操作
- update关联其他表批量更新数据-跨数据库-跨服务器Update时关联表条件更新
- update left join 多表关联更新,
- hibernate (多对多) 执行update更新操作时,关联表数据会被删除
- UPDATE与多表关联更新
- 【SQL】update关联更新
- Oracle Update多表关联更新
- Android 为什么当数据库改变时,与CursorAdapter关联的页面始终不更新
- 两表关联更新,用于update 回滚
- update关联其他表批量更新数据
- oracle UPDATE 多表关联更新
- 两表关联更新,用于update 回滚
- 在A、B两表之间有一个字段可以关联,现在我想用一条UPDATE语句更新A表中的某字段
- oracle update set select from 关联更新
- SQL脚本实现两张关联数据表之间批量更新UPDATE