更新的子查询中的应用介绍

基本知识

1、相关子查询,子查询无关

在一个非关联子查询、内部查询只有一次,并返回它的值到外部查询执行,那么外部查询使用其内部查询的处理返回值。在相关子查询、内部查询被执行一次每行由一个外部查询返回的数据。此外,该信息流在相关子查询是双向的。每排外部查询的值传递到子查询,子查询执行的每一行数据一次,并返回它的记录,然后做出的决定是基于外部查询返回的记录。

如:


选择o1.customerid,o1.orderid,o1.orderdate
从订单O1
在o1.orderdate =(选择马克斯(订单))
从订单O2
在o2.customerid = O1 CustomerID)。


是一个相关子查询


选择o1.customerid,o1.orderid,o1.orderdate
从订单O1
o1.orderdate在哪里
(选择前2 o2.orderdate
从订单O2
在o2.customerid = O1 CustomerID)。
为了通过CustomerID


是一个相关子查询

2,提示(提示)

In general optimization, the execution path of the statement is determined by the optimizer of the Oracle system, regardless of the rule based or cost based method.It's not the best way to choose such a path.So, Oracle provides a way to call a hint.It allows the programmer to select the execution path according to its own requirements, that is, to prompt the optimizer to execute the current statement according to what rules of execution.This can be better in performance than the Oracle optimization.

通常,程序员可以使用提示来优化决策:



L语句的优化方法;

l对于SQL语句,基于开销优化程序的对象;

l SQL语句的访问路径;

L连接语句的连接顺序;

l连接语句中的连接操作。

如果您希望优化器遵循程序员的要求,您必须在语句中给出提示。提示的有效范围是有限的,也就是说,提示的语句块可以根据提示符的请求执行:

l简单选择、更新、删除语句;

l复合句或子查询语句;

l构成查询的一部分(联合)。

指定的注释语句由++组成。语法如下:

{选择} {提示删除|更新| / * + |文本}。



{选择} {提示文本删除|更新| -- | }

请注意,在不直接在+ + +之后,同样也链接到写作。

警告:如果提示语句没有正确写入,Oracle会忽略语句。

常见的提示是:

命令以按from子句中指定的表的顺序连接。

use_nl强行指定两表之间的连接是一个嵌套循环(嵌套循环)

use_hash强行指定两表之间的连接是一个Hashi连接(hash join)

use_merge强行指定两表之间的连接是一个连接(归并排序合并连接)

push_subq让不相关子查询提前执行

索引被迫使用索引。

3,实施计划

在SQL开发人员的SQL窗口中,使用鼠标或键盘选择SQL语句,然后按F5,将有一个接口来执行计划解析。

4、更新的特点

更新系统的内部执行可以参考附录:更新事务的内部分析。

使用更新的基本点是

1)尽可能多地使用更新表上的索引,以减少不必要的更新。

2)更新后的数据源需要尽可能短的时间。如果无法完成,将更新内容插入中间表,然后对中间表进行索引并更新它。

3)如果主键被更新,建议删除并插入。

5、示例表

下面将围绕以下两个表进行详细阐述:

创建表的表(日期/时间工作日期VARCHAR2(8)、奇诺VARCHAR2(15),val1,val2号);

创建表tab2(日期/时间工作日期VARCHAR2(8)、奇诺VARCHAR2(15),val1,val2号);

创建表的表3(日期/时间工作日期VARCHAR2(8)、奇诺VARCHAR2(15),val1,val2号);

创建表的表4(日期/时间工作日期VARCHAR2(8)、奇诺VARCHAR2(15),val1,val2号);



日期/时间工作日期,Cino是两个表的关键字,以及默认不建主键索引。

二,更新两个案例

更新更新表不超过两例:根据相关子查询,字段更新;更新范围是由相关子查询的限制。如果有第三例,这是第一次两叠加。

1、根据相关子查询更新的领域


更新表T
集(val1,val2)=(选择val1,val2)
从表2
在日期/时间工作日期= t.workdate
Cino = t.cino);


更新表的相应字段通过TAB2。当SQL语句执行时,系统读取从表一行和一行记录,然后找到相应的字段更新通过关联子查询,子查询是否能迅速通过相关表的条件找到相应的记录是优化的必要条件,因此一般需要建立一个独特的或正常的指标用在对高排重。用于执行的时间可能是在表条目数量(查询使用的时间记录在一个记录表2 1 +时间)*表的记录数。

如果子查询条件复杂,如以下:


更新表T
集(val1,val2)=(选择val1,val2)
从表2 TT
存在(选择1)
从表3
在日期/时间工作日期= tt.workdate
Cino = TT Cino)。
和日期/时间工作日期= t.workdate
Cino = t.cino);


在这个时候,在更新表的所有记录将成倍增加在子查询的时间。如果在表的记录数是大的,这个更新的声明几乎是不可能的。

解决方案是处理提取的查询,到表中间,然后在索引表的中间设置中间表,而不是子查询,这样可以大大提高速度:


插入表4
选择日期/时间工作日期,金格,val1,val2
从表2 TT
存在(选择1)
从表3
在日期/时间工作日期= tt.workdate
Cino = TT Cino);
创建表4指数tab4_ind01(日期/时间工作日期,Cino);

更新表T
集(val1,val2)=(选择val1,val2)
从表4 TT
在日期/时间工作日期= t.workdate
Cino = t.cino);


2、资格更新范围无关的子查询


更新表T
集val1 = 1
在(日期/时间工作日期,Cino)在(选择日期/时间工作日期,Cino从表2)


更新表的相应记录val1现场根据数据范围的TAB2提供。

在这种情况下,默认的实现往往是选择日期/时间工作日期第一次执行,Cino从TAB2子查询,形成系统的观点,然后选择在表的查询记录,是否有相应的日期/时间工作日期系统观华组合,如果更新表,如果没有,再选择下一个记录。这样的查询时间大致相等:子查询的查询时间+(在表选择一个记录时间+系统中查看全表扫描找到一个记录时间)*记录表编号。在系统视图,全表扫描在记录时间搜索根据不同的这对大小。如果对记录数很小,系统可以直接读表系统;如果对记录数系统不能形成系统视图,那么每次更新动作,把查询时间、速度都会非常慢。

这种情况有两种优化方法。

1)添加的日期/时间工作日期指标,奇诺场TAB1,并添加提示。

修改后的SQL语句如下所示:


更新 / * +命令use_nl(sys,t)t /表
集val1 = 1
在(日期/时间工作日期,Cino)在(选择日期/时间工作日期,Cino从表2)


其中系统代表了系统的观点。如果命令提示符不加,系统会默认为TAB1表作为驱动表,然后全表扫描的表就完成了。当你添加一个提示,运用系统论的观点,即选择日期/时间工作日期,Cino从TAB2,作为司机表,在正常情况下,速度可以提高很多。

2)在日期/时间工作日期在TAB2表的Cino字段添加到索引和SQL语句改写。


更新表T
集val1 = 1
存在(选择1)
从表2
在日期/时间工作日期= t.workdate
Cino = t.cino)


三、指数问题

更新索引的使用是特殊的,有时可以使用全索引,但实际上只使用部分索引,因此建议编写复合索引的所有字段。

例如:


更新 / * +命令use_nl(sys,t)t /表
集val1 = 1
在Cino(Cino选择从表2)
和日期/时间工作日期= '200506


这个SQL语句不充分利用复合索引日期/时间工作日期+奇诺的表。能被利用的只有日期/时间工作日期= '200506的约束。

如果是这样写的,没有问题:


更新 / * +命令use_nl(sys,t)t /表
集val1 = 1
在(日期/时间工作日期,Cino)在(选择日期/时间工作日期,Cino从表2)