基础知识

1, 关联子查询和非关联子查询

在非关联子查询中,内部查询只执行一次并返回它的值给外部查询,然后外部查询在它的处理中使用内部查询返回给它的值。而在关联子查询中,对于外部查询返回的每一行数据,内部查询都要执行一次。另外,在关联子查询中是信息流是双向的。外部查询的每行数据传递一个值给子查询,然后子查询为每一行数据执行一次并返回它的记录。然后,外部查询根据返回的记录做出决策。

如:

SELECT o1.CustomerID, o1.OrderID, o1.OrderDate

FROM Orders o1

WHERE o1.OrderDate = (SELECT Max(OrderDate)

FROM Orders o2

WHERE o2.CustomerID = o1.CustomerID)

是一个关联子查询

SELECT o1.CustomerID, o1.OrderID, o1.OrderDate

FROM Orders o1

WHERE o1.OrderDate IN

(SELECT TOP 2 o2.OrderDate

FROM Orders o2

WHERE o2.CustomerID = o1.CustomerID)

ORDER BY CustomerID

是一个非关联子查询

2, 提示(HINT)

一般在优化时,无论采用基于规则的或是基于代价的方法,由Oracle系统的优化器来决定语句的执行路径。这样的选择的路径不要见得是最好的。所以,Oracle提供了一种方法叫提示的方法。它可以让编程人员按照自己的要求来选择执行路径,即提示优化器该按照什么样的执行规则来执行当前的语句。这样可以在性能上比起Oracle优化自主决定要好些。

通常情况下,编程人员可以利用提示来进行优化决策。通过运用提示可以对下面内容进行指定:

l SQL语句的优化方法;

l 对于某条SQL语句,基于开销优化程序的目标;

l SQL语句访问的访问路径;

l 连接语句的连接次序;

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

如果希望优化器按照编程人员的要求执行,则要在语句中给出提示。提示的有效范围有限制,即有提示的语句块才能按照提示要求执行。下面语句可以指定提示:

l 简单的SELECT ,UPDATE ,DELETE 语句;

l 复合的主语句或子查询语句;

l 组成查询(UNION)的一部分。

提示的指定有原来的注释语句在加“+”构成。语法如下:

[ SELECT | DELETE|UPDATE ] /*+ [hint | text ] */

[ SELECT | DELETE|UPDATE ] --+ [hint | text ]

注意在“/*”后不要空就直接加“+”,同样 “--+”也是连着写。

警告:如果该提示语句书写不正确,则Oracle就忽略掉该语句。

常见的提示有:

Ordered 强制按照from子句中指定的表的顺序进行连接

Use_NL 强制指定两个表间的连接方式为嵌套循环(Nested Loops)

Use_Hash 强制指定两个表间的连接方式为哈希连接(Hash Join)

Use_Merge 强制指定两个表间的连接方式为合并排序连接(Merge Join)

Push_Subq 让非关联子查询提前执行

Index 强制使用某个索引

3, 执行计划

在PL/SQL Developer的SQL WINDOWS中用鼠标或键盘选中SQL语句,然后按F5,就会出现执行计划解析的界面:

4, Update的特点

Update的系统内部执行情况可以参照附文:对update事务的内部分析.doc

使用Update的基本要点就是,

1) 尽量使用更新表上的索引,减少不必要的更新

2) 更新的数据来源花费时间尽可能短,如果无法做到就把更新内容插入到中间表中,然后给中间表建上索引,再来更新

3) 如果更新的是主键,建议删除再插入。

5, 示例用表

后面的阐述将围绕以下两张表展开:

Create table tab1 (workdate varchar2(8), cino varchar2(15), val1 number, val2 number);

Create table tab2 (workdate varchar2(8), cino varchar2(15), val1 number, val2 number);

Create table tab3 (workdate varchar2(8), cino varchar2(15), val1 number, val2 number);

Create table tab4 (workdate varchar2(8), cino varchar2(15), val1 number, val2 number);

workdate, cino为两张表的关键字,默认情况没有建主键索引。

二,Update两种情况

用Update更新某个表,无外乎是两种情况:根据关联子查询,更新字段;通过非关联子查询,限定更新范围。如果还有第三种情况,那就是前两种情况的叠加。

1, 根据关联子查询,更新字段

Update tab1 t

Set (val1, val2) = (select val1, val2

from tab2

where workdate = t.workdate

and cino = t.cino);

通过tab2来更新tab1的相应字段。执行SQL语句时,系统会从tab1中一行一行读记录,然后再通过关联子查询,找到相应的字段来更新。关联子查询能否通过tab1的条件快速的查找到对应记录,是优化能否实现的必要条件。所以一般都要求在tab2上建有Unique或者排重性较高的Normal索引。执行所用时间大概为(查询tab1中一条记录所用的时间 + 在tab2中查询一条记录所用的时间)* tab1中的记录条数。

如果子查询条件比较复杂,如以下语句:

Update tab1 t

Set (val1, val2) = (select val1, val2

from tab2 tt

where exists (select 1

from tab3

where workdate = tt.workdate

and cino = tt.cino)

and workdate = t.workdate

and cino = t.cino);

这时更新tab1中的每条记录花费在子查询上的时间将成倍增加,如果tab1中的记录数较多,这种更新语句几乎是不可完成。

解决方式是,把子查询提取出来,做到中间表中,然后给中间表建上索引,用中间表来代替子查询,这样速度就能大大提高:

Insert into tab4

select workdate, cino, val1, val2

from tab2 tt

where exists (select 1

from tab3

where workdate = tt.workdate

and cino = tt.cino);

create index tab4_ind01 on tab4(workdate, cino);

Update tab1 t

Set (val1, val2) = (select val1, val2

from tab4 tt

where workdate = t.workdate

and cino = t.cino);

2, 通过非关联子查询,限定更新范围

Update tab1 t

set val1 = 1

where (workdate, cino) in (select workdate, cino from tab2)

根据tab2提供的数据范围,来更新tab1中的相应记录的val1字段。

在这种情况下,系统默认执行方式往往是先执行select workdate, cino from tab2子查询,在系统中形成系统视图,然后在tab1中选取一条记录,查询系统视图中是否存在相应的workdate, cino组合,如果存在,则更新tab1,如果不存在,则选取下一条记录。这种方式的查询时间大致等于:子查询查询时间 + (在tab1中选取一条记录的时间 + 在系统视图中全表扫描寻找一条记录时间)* tab1的记录条数。其中“在系统视图中全表扫描寻找一条记录时间”会根据tab2的大小而有所不同。若tab2记录数较小,系统可以直接把表读到系统区中;若tab2记录数多,系统无法形成系统视图,这时会每一次更新动作,就把子查询做一次,速度会非常的慢。

针对这种情况的优化有两种

1) 在tab1上的workdate, cino字段上加入索引,同时增加提示。

修改以后的SQL语句如下:

Update /*+ordered use_nl(sys, t)*/ tab1 t

set val1 = 1

where (workdate, cino) in (select workdate, cino from tab2)

其中sys表示系统视图。如果不加入ordered提示,系统将会默认以tab1表作为驱动表,这时就要对tab1作全表扫描。加入提示后,使用系统视图,即select workdate, cino from tab2,作为驱动表,在正常情况下,速度能提高很多。

2) 在tab2表上的workdate, cino字段加入索引,同时改写SQL语句:

Update tab1 t

set val1 = 1

where exists (select 1

from tab2

where workdate = t.workdate

and cino = t.cino)

三,索引问题

update索引的使用比较特殊,有时看起来能用全索引,但实际上却只用到一部分,所以建议把复合索引的各字段写在一起。

例如:

Update /*+ordered use_nl(sys, t)*/ tab1 t

set val1 = 1

where cino in (select cino from tab2)

and workdate = '200506'

这条SQL语句是不能完全用到tab1上的复合索引workdate + cino的。能用到的只是workdate='200506'的约束。

如果写成这样,就没问题:

Update /*+ordered use_nl(sys, t)*/ tab1 t

set val1 = 1

where (workdate, cino) in (select workdate, cino from tab2)

mysql中update子查询,update 子查询使用介绍相关推荐

  1. SQL优化之一则MySQL中的DELETE、UPDATE 子查询的锁机制失效案例

    关注"数据和云",精彩不容错过 前言 开发与维护人员避免不了与 in/exists.not in/not exists 子查询打交道,接触过的人可能知道 in/exists.not ...

  2. MySql中怎样使用case-when实现判断查询结果返回

    场景 在对Mysql中的数据查询时,某些字段比如是否怎样样,在数据库中存储的是0和1. 如果想在查询时根据值是0和1进而返回是和否怎样编写查询语句. 注: 博客: https://blog.csdn. ...

  3. mysql中如何取消1000行的查询限制?

    在使用数据库时,常常会有需要使用select语句查询表的情况.当使用select * 进行查询时,mysql中默认查询表的前1000行,也就是说如果表中的数据库超过了1000行,查询结果就会显示不完整 ...

  4. MySQL中 ON DUPLICATE KEY UPDATE语法的使用

    MySQL ON DUPLICATE KEY UPDATE 为Mysql特有语法 ON DUPLICATE KEY UPDATE 用法与说明 Mysql中INSERT ... ON DUPLICATE ...

  5. MYSQL中ON DUPLICATE KEY UPDATE对数据进行insertOrUpdate操作

    本文来自:高爽|Coder,原文地址:[url]http://blog.csdn.net/ghsau/article/details/23557915[/url],转载请注明. 向数据库插入记录时,有 ...

  6. mysql中的union用法以及子查询综合应用

    union查询就是把2条或者多条sql语句的查询结果,合并成一个结果集. 如:sql1: N行,sql2: M行,sql1 union sql2 ---> N+M行 1.能否从2张表查询再uni ...

  7. 使用navicat工具将mysql中的insert、update等sql语句生成为delphi的格式

    1.打开表. 2.复制为update语句. 3.粘贴到笔记本中,使用替换工具,去除引号. 粘贴到查询编辑器中,含引号复制为delphi语句. 结果. 'UPDATE wqkdatabase.cp_gr ...

  8. MySQL中的LEFT JOIN ON (where)查询

    LEFT JOIN ON的使用语法: select [需要查询的字段] from [table_name1] left join [table_name2] on [两个表关联的条件] (where ...

  9. mysql中3张表如何关联查询_mysql三张表关联查询

    三张表,需要得到的数据是标红色部分的.sql如下: select a.uid,a.uname,a.upsw,a.urealname,a.utel,a.uremark, b.rid,b.rname,b. ...

  10. node.js mysql 不退出,mysql - 错误:使用NodeJS在MySQL中调用退出后无法排队查询 - SO中文参考 - www.soinside.com...

    我正在尝试运行此NodeJs代码以在Mysql DB中添加数据:app.post("/taxi",(req,res)=>{ let model=req.body.model; ...

最新文章

  1. 急!!!求从字符串中提取形如: div([MC0010000000006],此若干个字符或数字,0) 的正则表达式...
  2. mac安装mysql8.0.11_【MySQL】Mac安装MySQL(V8.0.15)蹚坑记录
  3. Cxf + Spring3.0 入门开发WebService
  4. python下载软件-python下载工具
  5. python连接mysql数据库数据库_python如何连接mysql数据库
  6. R语言——linux离线安装R包
  7. Apriori算法进行关联分析(2)
  8. 在reader中勾选pdf复选框_Adobe Acrobat和Reader PDF文件处理缓冲区溢出漏洞
  9. QtCreate不能使用代码提示功能
  10. 很少人知道,但是非常实用的 Python 库
  11. python获取磁盘剩余空间的方法
  12. [转]在ubuntu下安装sublime text
  13. c语言命名规则 [转载]
  14. UNIX网络编程之一:代码环境搭建
  15. matlab泰勒 习题,泰勒公式及其应用典型例题
  16. u盘启动会进入w ndows安装程序,u启动一键u盘安装Ghost Win7系统教程_u启动
  17. 中国新鲜杏子行业市场供需与战略研究报告
  18. 【Codewars】Bouncing Balls
  19. 怎么把英文翻译成中文?手机中英翻译的简单方法
  20. Python中第三方库-Faker应用

热门文章

  1. 阿里云邮箱登录日志中有异地IP登录是怎么回事?该怎么办?
  2. 计算机组老师颁奖词,获奖教师的颁奖词
  3. 致谢计算机组成原理老师的致谢,论文致谢优秀.doc
  4. 石英晶振的基本原理与电路设计
  5. 红旗linux hba卡wwn,Redhat Linux下安装HBA卡并查看WWN号
  6. 支小蜜智慧食堂刷脸就餐让学生不再刷卡吃饭
  7. 清华大学计算机系高考生源,清华在京录取圆满结束:生源好、质量优、扩幅大(转贴)...
  8. Oracle-08:连接查询
  9. Ruby On Rails-2.0.2源代码分析(1)-Rails的启动
  10. 《精彩网址大全——工商经济科学教育卷》内容简介