要将表的限制条件写到与该表同级别的where中
测试目的:将朱查询的限制条件放到子查询的where中,查看性能影响。
测试数据:
create table t1 as select object_id,object_name from dba_objects;
create table t2 as select object_id,object_name from user_objects;
create table t3 as select rownum object_id,table_name object_name from user_tables;
analyze table t1 compute statistics for table for all columns;
analyze table t2 compute statistics for table for all columns;
analyze table t3 compute statistics for table for all columns;
SQL> select count(*) from t1;
COUNT(*)
----------
26341
SQL> select count(*) from t2;
COUNT(*)
----------
13135
SQL> select count(*) from t3;
COUNT(*)
----------
5891
开始测试:
1.主查询条件出现在子查询的where中(确实有开发是这样写的SQL,或许是动态生成SQL或者因为不太了解SQL编写规范手动写的):
SQL> select *
2 from t1
3 where t1.object_id in
4 (select t2.object_id
5 from t2
6 where t1.object_name in (select t3.object_name from t3));
已选择5890行。
执行计划
----------------------------------------------------------
Plan hash value: 1276346997
----------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)| Time |
----------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 25583 | 2723K| | 244K (1)| 00:48:50 |
|* 1 | HASH JOIN SEMI | | 25583 | 2723K| 2280K| 244K (1)| 00:48:50 |
| 2 | TABLE ACCESS FULL | T1 | 25585 | 1973K| | 32 (0)| 00:00:01 |
| 3 | VIEW | VW_SQ_1 | 77M| 2213M| | 89634 (1)| 00:17:56 |
| 4 | NESTED LOOPS | | 77M| 2213M| | 89634 (1)| 00:17:56 |
| 5 | TABLE ACCESS FULL| T2 | 13135 | 166K| | 17 (0)| 00:00:01 |
| 6 | TABLE ACCESS FULL| T3 | 5891 | 97K| | 7 (0)| 00:00:01 |
----------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - access("T1"."OBJECT_ID"="T2.OBJECT_ID" AND "T1"."OBJECT_NAME"="ITEM_1")
Note
-----
- dynamic sampling used for this statement (level=4)
统计信息
----------------------------------------------------------
37 recursive calls
0 db block gets
316742 consistent gets
0 physical reads
0 redo size
184781 bytes sent via SQL*Net to client
4728 bytes received via SQL*Net from client
394 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
5890 rows processed
从执行计划可以看出,其实t2和t3走了笛卡尔积(SQL中这两个确实没有关联条件,从两个表nested loops后的返回基数77M可以看出,这两个表是走了笛卡尔积的)。笛卡尔积结果跟t1做hash join,t1将object_name传递给nested loop是的结果。返回5890条数据,消耗316742逻辑读。
这种性能方面的问题,我们是完全可以通过注意SQL的编码规范来规避的。
2.改写SQL,将主查询的限制条件放到与该其同级别的WHERE中。
SQL> select *
2 from t1
3 where t1.object_id in (select t2.object_id from t2)
4 and t1.object_name in (select object_name from t3);
已选择5890行。
执行计划
----------------------------------------------------------
Plan hash value: 3620957986
------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 13135 | 1398K| 60 (4)| 00:00:01 |
|* 1 | HASH JOIN RIGHT SEMI | | 13135 | 1398K| 60 (4)| 00:00:01 |
| 2 | TABLE ACCESS FULL | T3 | 5891 | 97K| 9 (0)| 00:00:01 |
|* 3 | HASH JOIN RIGHT SEMI| | 13135 | 1180K| 50 (2)| 00:00:01 |
| 4 | TABLE ACCESS FULL | T2 | 13135 | 166K| 17 (0)| 00:00:01 |
| 5 | TABLE ACCESS FULL | T1 | 25585 | 1973K| 32 (0)| 00:00:01 |
------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - access("T1"."OBJECT_NAME"="T3"."OBJECT_NAME")
3 - access("T1"."OBJECT_ID"="T2"."OBJECT_ID")
Note
-----
- dynamic sampling used for this statement (level=4)
统计信息
----------------------------------------------------------
0 recursive calls
0 db block gets
575 consistent gets
0 physical reads
0 redo size
184781 bytes sent via SQL*Net to client
4728 bytes received via SQL*Net from client
394 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
5890 rows processed
从执行计划来看,Oracle选择的表连接顺序都是最优的,逻辑读也从原来的316742下降到575,速度也提升很多。
切记:写SQL时一定要将对表的限制条件写到与该表同级别的where条件里。
要将表的限制条件写到与该表同级别的where中的更多相关文章
- 怎样加快master数据库的写操作?分表原则!将表水平划分!或者添加写数据库的集群
1.怎样加快master数据库的写操作?分表原则!将表水平划分!减少表的锁定时间!!! 或者或者添加写数据库的集群!!!或者添加写数据库的集群!!! 2.既然分表了,就一定要注意分表的规则!要在代码层 ...
- 用for; while...do; do...while; 写出九九乘法表
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- SQL纯手写创建数据库到表内内容
建表啥的只点点鼠标,太外行了,不如来看看我的纯手写,让表从无到有一系列:还有存储过程临时表,不间断的重排序: 一:建数据库 create Database Show on primary ( name ...
- 用Java写了一个程序,将一个Mysql库中的表,迁移到另外一个server上的Mysql库中
用Navicat做数据迁移,因为数据量比较大,迁移过过程中一个是进展不直观,另外就是cpu占用率高的时候,屏幕跟死机了一样点不动按钮,不好中断. 想了想,干脆自己写一个. 在网上找了一个sqllite ...
- 使用PowerShell读、写、删除注册表键值
访问注册表键值 在PowerShell中,用户可以通过类似于HKCU:(作为HKEY_CURRENT_USER)和HKLM:(代表HKEY_LOCAL_MATCHINE)的虚拟驱动器访问注册表键值. ...
- SQLServer将服务器A表写到服务器B表
不同服务器数据库之间的数据操作 --创建链接服务器 exec sp_addlinkedserver 'ITSV ', ' ', 'SQLOLEDB ', '远程服务器名或ip地址 ' ...
- 一个7重嵌套表EF添加语句,注意子表赋值过程中只需写子表主键赋值,不需要写子表外键=父表主键。EF创建时会自动将子表外键设为与父表主键相等
AIRPORT_HELIPORT tt = new AIRPORT_HELIPORT() { AIRPORT_HELIPORT_UUID = Gui ...
- mysql数据库 myisam数据存储引擎 表由于索引和数据导致的表损坏 的修复 和检查
一.mysqlcheck 进行表的检查和修复 1.检查mysqlisam存储引擎表的状态 #mysqlcheck -uuser -ppassword database table -c #检查单 ...
- [置顶] ※数据结构※→☆线性表结构(stack)☆============栈 序列表结构(stack sequence)(六)
栈(stack)在计算机科学中是限定仅在表尾进行插入或删除操作的线性表.栈是一种数据结构,它按照后进先出的原则存储数据,先进入的数据被压入栈底,最后的数据在栈顶,需要读数据的时候从栈顶开始弹出数据.栈 ...
随机推荐
- js与事件处理
1. <a href="javascript:showModalDialog('../TrainingReq/QryTermCourseInfo.aspx?TermCourseID=& ...
- Linux系列:Ubuntu虚拟机设置固定IP上网(配置IP、网关、DNS、防止resolv.conf被重写)
虚拟机里设置上网方式为NAT最方便,因为无需手动设置即可上网,但是NAT的上网方式默认是DHCP动态分配IP的,这意味着你每次重启虚拟机都 有不一样的IP地址,这对一般用户没任何问题.但是如果你的机子 ...
- [React] React Fundamentals: Accessing Child Properties
When you're building your React components, you'll probably want to access child properties of the m ...
- Percona-toolkit的安装和配置-杨建荣的学习笔记
http://blog.itpub.net/23718752/viewspace-2091818/#rd
- quartz多个scheduler实现
1.首先排除错误用法 SchedulerFactory schedulerFactory = new StdSchedulerFactory(); Scheduler scheduler = sche ...
- Android 自学之线性布局 LinearLayout
线性布局(LinearLayout),线性布局有点想AWT编程里面的FolwLayout,他们都会将容器里面的组件挨个的排列起来. 他们最大的区别在于:Android的线性布局不会换行:AWT里面的F ...
- Leetcode Python Solution(continue update)
leetcode python solution 1. two sum (easy) Given an array of integers, return indices of the two num ...
- OpenSSH Client信息泄露和缓冲区溢出漏洞
一.风险简述: 2016年1月14日OpenSSH发布官方公告称,OpenSSH Client 5.4~7.1版本中未公开说明的功能(Roaming)存在信息泄漏和缓冲区溢出漏洞,此漏洞可能导致您通过 ...
- shell记录
查看linux服务器有哪些人曾经ssh登陆过,以及他们的登录信息 who查看当前正在ssh链接中的 last查看最近被链接过的 who last netstat -nltp -an ...
- modelsim仿真时让状态机波形显示状态的名字
在使用Verilog编写有限状态机等逻辑的时候,状态机的各个状态通常以参数表示(如IDLE等).当使用ModelSim仿真的时候,状态机变量在wave窗口中以二进制编码的形式显示,如下面所示,这种显示 ...