nested loop,sort merge join,hash join

-- Create table
create table T_MPED_INFO
(
  MPED_ID             INTEGER not null,
  MPED_INDEX          NUMBER(6) not null,
  MPED_NAME           VARCHAR2(50),
  PARAM_FLAG          CHAR(1),
  COMM_PORT           NUMBER(5),
  MPED_TYPE           CHAR(1),
  USER_FLAG           CHAR(1),
  REMARK              VARCHAR2(50),
  METER_ID            INTEGER,
  TERMINAL_ID         INTEGER,
  COLL_ID             INTEGER,
  MP_MODE             VARCHAR2(8),
  MEASURE_SITE        VARCHAR2(8),
  DEVICE_NO           VARCHAR2(10),
  MEASURE_ADD         VARCHAR2(40),
  CUST_ID             INTEGER,
  IS_TOTALMETER       CHAR(1),
  IS_METERFLAG        CHAR(1),
  CREATE_DATE         VARCHAR2(20) default TO_CHAR(sysdate,'YYYY-MM-DD'),
  PARAM_FLAG_DATETIME VARCHAR2(20) default to_char(sysdate,'yyyy-mm-dd hh24:mi:ss'),
  OPERATOR            VARCHAR2(20),
  OPERATETIME         VARCHAR2(20),
  LINE_ID             INTEGER
)
tablespace TS_BASE_DATA
  pctfree 10
  initrans 1
  maxtrans 255
  storage
  (
    initial 64K
    next 1M
    minextents 1
    maxextents unlimited
  );
-- Add comments to the table 

-- Create/Recreate primary, unique and foreign key constraints 
alter table T_MPED_INFO
  add constraint PK_T_MPED_INFO primary key (MPED_ID)
  using index 
  tablespace TS_BASE_IDX
  pctfree 10
  initrans 2
  maxtrans 255
  storage
  (
    initial 64K
    next 1M
    minextents 1
    maxextents unlimited
  );
-- Create/Recreate indexes 
create index FK1_T_MPED_INFO on T_MPED_INFO (METER_ID)
  tablespace TS_BASE_IDX
  pctfree 10
  initrans 2
  maxtrans 255
  storage
  (
    initial 64K
    next 1M
    minextents 1
    maxextents unlimited
  );
create unique index FK2_T_MPED_INFO on T_MPED_INFO (TERMINAL_ID, MPED_INDEX)
  tablespace TS_BASE_IDX
  pctfree 10
  initrans 2
  maxtrans 255
  storage
  (
    initial 64K
    next 1M
    minextents 1
    maxextents unlimited
  );
create index FK3_T_MPED_INFO on T_MPED_INFO (CUST_ID)
  tablespace TS_BASE_IDX
  pctfree 10
  initrans 2
  maxtrans 255
  storage
  (
    initial 64K
    next 1M
    minextents 1
    maxextents unlimited
  );

-- Create table
create table T_METER_INFO
(
  METER_ID          INTEGER not null,
  METER_NAME        VARCHAR2(50),
  METER_NUMBER      VARCHAR2(20),
  DEVICENO          VARCHAR2(20),
  LINE_STYLE.        CHAR(1),
  PROD_FACTORY      VARCHAR2(50),
  METERTYPENO       VARCHAR2(20),
  METER_TYPE        CHAR(1),
  FACTORYNO         VARCHAR2(20),
  RETURN_ZERO_VALUE NUMBER(8),
  SHOW_WORD         VARCHAR2(20),
  IS_METER_FLAG     CHAR(1),
  ORIENTATION       CHAR(1),
  ADDRESS           VARCHAR2(50),
  LONGITUDE         NUMBER(8),
  LATITUDE          NUMBER(8),
  DOUBLERATE        NUMBER(8),
  ENERGYRATE1       NUMBER(11,4),
  ENERGYRATE2       NUMBER(11,4),
  ENERGYRATE3       NUMBER(11,4),
  ENERGYRATE4       NUMBER(11,4),
  PT                VARCHAR2(20),
  CT                VARCHAR2(20),
  CHECK_DATE        VARCHAR2(20),
  INTEGER_CNT       NUMBER(3),
  DECIMAL_CNT       NUMBER(3),
  RATE_CNT          NUMBER(3),
  I_SPEC            CHAR(1),
  U_SPEC            CHAR(1),
  IS_TOTALMETER     CHAR(1),
  CUST_ID           INTEGER,
  METER_STATUS      CHAR(1),
  REMOTE_STATUS     CHAR(1),
  REMARK            VARCHAR2(50),
  PRCE_GRADE        CHAR(1),
  TOTALENERGY       NUMBER(11,4),
  SET_NUMBER        VARCHAR2(20),
  MP_NAME           VARCHAR2(50),
  MP_NUMBER         VARCHAR2(20),
  MP_ADDR           VARCHAR2(50),
  READ_METER_NUM    NUMBER,
  PRP_ENERGYVALUE   NUMBER(11,4),
  CHARGE_SIGN       CHAR(1) default 0,
  RUN_TIME          DATE,
  OPERATOR          VARCHAR2(20),
  OPERATETIME       VARCHAR2(20),
  CITY_ID           NUMBER
)
tablespace TS_BASE_DATA
  pctfree 10
  initrans 1
  maxtrans 255
  storage
  (
    initial 64K
    next 1M
    minextents 1
    maxextents unlimited
  );
-- Add comments to the table 

-- Create/Recreate primary, unique and foreign key constraints 
alter table T_METER_INFO
  add constraint PK_METER_ID primary key (METER_ID)
  using index 
  tablespace TS_BASE_IDX
  pctfree 10
  initrans 2
  maxtrans 255
  storage
  (
    initial 64K
    next 1M
    minextents 1
    maxextents unlimited
  );
-- Create/Recreate indexes 
create index FK1_T_METER_INFO on T_METER_INFO (CUST_ID)
  tablespace TS_BASE_IDX
  pctfree 10
  initrans 2
  maxtrans 255
  storage
  (
    initial 64K
    next 1M
    minextents 1
    maxextents unlimited
  );
create index FK2_T_METER_INFO on T_METER_INFO (CITY_ID)
  tablespace TS_BASE_IDX
  pctfree 10
  initrans 2
  maxtrans 255
  storage
  (
    initial 64K
    next 1M
    minextents 1
    maxextents unlimited
  );


t_mped_info,t_meter_info大概有300W记录数。


--nested loops,可以用于(非等值,等值)连接,当过滤后的记录数比较小时才会nested loops

select * from t_mped_info a,t_meter_info b 
where a.meter_id=b.meter_id and a.mped_id=10000;

SELECT STATEMENT, GOAL = ALL_ROWS 5 1 124 5 ALL_ROWS 40217
 NESTED LOOPS 5 1 124 5 40217
  TABLE ACCESS BY INDEX ROWID PTEST T_MPED_INFO 3 1 76 3 ANALYZED 23004
   INDEX UNIQUE SCAN PTEST PK_T_MPED_INFO 2 1 2 ANALYZED 15293
  TABLE ACCESS BY INDEX ROWID PTEST T_METER_INFO 2 3181500 152712000 2 ANALYZED 17213
   INDEX UNIQUE SCAN PTEST PK_METER_ID 1 1 1 ANALYZED 9021

select * from t_mped_info a,t_meter_info b 
where a.meter_id>b.meter_id and a.mped_id=10000;

SELECT STATEMENT, GOAL = ALL_ROWS 9903 1590750 197253000 9646 ALL_ROWS 3657729904
 NESTED LOOPS 9903 1590750 197253000 9646 3657729904
  TABLE ACCESS BY INDEX ROWID PTEST T_MPED_INFO 3 1 76 3 ANALYZED 23004
   INDEX UNIQUE SCAN PTEST PK_T_MPED_INFO 2 1 2 ANALYZED 15293
  TABLE ACCESS FULL PTEST T_METER_INFO 9900 1590750 76356000 9643 ANALYZED 3657706900
  
--nested loops,where过滤后的记录数小的表为driving table  
select * from t_mped_info a,t_meter_info b 
where a.meter_id=b.meter_id and a.meter_id=90;

SELECT STATEMENT, GOAL = ALL_ROWS 6 1 124 6 ALL_ROWS 47279
 NESTED LOOPS 6 1 124 6 47279
  TABLE ACCESS BY INDEX ROWID PTEST T_METER_INFO 3 1 48 3 ANALYZED 23484
   INDEX UNIQUE SCAN PTEST PK_METER_ID 2 1 2 ANALYZED 15293
  TABLE ACCESS BY INDEX ROWID PTEST T_MPED_INFO 3 1 76 3 ANALYZED 23794
   INDEX RANGE SCAN PTEST FK1_T_MPED_INFO 2 1 2 ANALYZED 15493
  


--走sort merge join,可以用于(非等值,等值)连接
select * from t_mped_info a,t_meter_info b 
where a.meter_id>b.meter_id and a.mped_id>90;

SELECT STATEMENT, GOAL = ALL_ROWS 35722232 5060827957500 627542666730000 99009 ALL_ROWS 506092942099254
 MERGE JOIN 35722232 5060827957500 627542666730000 99009 506092942099254
  SORT JOIN 51751 3181411 241787236 51533 3091937408
   TABLE ACCESS BY INDEX ROWID PTEST T_MPED_INFO 51751 3181411 241787236 51533 ANALYZED 3091937408
    INDEX FULL SCAN PTEST FK1_T_MPED_INFO 6815 3243986 6766 ANALYZED 696980863
  SORT JOIN 47995 3181500 152712000 47476 7372561847
   TABLE ACCESS FULL PTEST T_METER_INFO 9900 3181500 152712000 9643 ANALYZED 3657706900


select emp.ename,dept.dname
from emp,dept
where emp.deptno=dept.deptno;

| 0 | SELECT STATEMENT | | 12 | 264 | 8 (25)| 00:00:01 |
| 1 | MERGE JOIN | | 12 | 264 | 8 (25)| 00:00:01 |
| 2 | SORT JOIN | | 4 | 52 | 4 (25)| 00:00:01 |
| 3 | TABLE ACCESS FULL| DEPT | 4 | 52 | 3 (0)| 00:00:01 |
|* 4 | SORT JOIN | | 12 | 108 | 4 (25)| 00:00:01 |
|* 5 | TABLE ACCESS FULL| EMP | 12 | 108 | 3 (0)| 00:00:01 |


--走hash join,不可以用于非等值连接,只能用于等值连接,当where后的记录数较大时会选择hash join
select * from t_mped_info a,t_meter_info b 
where a.meter_id=b.meter_id and a.mped_id>90;

SELECT STATEMENT, GOAL = ALL_ROWS 42881 3181411 394494964 42365 ALL_ROWS 7325536675
 HASH JOIN 42881 3181411 394494964 42365 7325536675
  TABLE ACCESS FULL PTEST T_METER_INFO 9900 3181500 152712000 9643 ANALYZED 3657706900
  TABLE ACCESS FULL PTEST T_MPED_INFO 10634 3181411 241787236 10471 ANALYZED 2311414346


select * from t_mped_info a,t_meter_info b 
where a.meter_id=b.meter_id;
 
SELECT STATEMENT, GOAL = ALL_ROWS 42881 3181411 394494964 42365 ALL_ROWS 7325536675
 HASH JOIN 42881 3181411 394494964 42365 7325536675
  TABLE ACCESS FULL PTEST T_METER_INFO 9900 3181500 152712000 9643 ANALYZED 3657706900
  TABLE ACCESS FULL PTEST T_MPED_INFO 10634 3181411 241787236 10471 ANALYZED 2311414346
  
 
 
--nested loops,结果集相对小
嵌套循环连接的工作方式是这样的: 
1、 Oracle首先选择一张表作为连接的驱动表,这张表也称为外部表(Outer Table)。由驱动表进行驱动连接的表或数据源称为内部表(Inner Table)。 
2、 提取驱动表中符合条件的记录,与被驱动表的连接列进行关联查询符合条件的记录。在这个过程中,Oracle首先提取驱动表中符合条件的第一条记录,再与内部表的连接列进行关联查询相应的记录行。在关联查询的过程中,Oracle会持续提取驱动表中其他符合条件的记录与内部表关联查询。这两个过程是并行进行的,因此嵌套循环连接返回前几条记录的速度是非常快的。在这里需要说明的是,由于Oracle最小的IO单位为单个数据块,因此在这个过程中Oracle会首先提取驱动表中符合条件的单个数据块中的所有行,再与内部表进行关联连接查询的,然后提取下一个数据块中的记录持续地循环连接下去。当然,如果单行记录跨越多个数据块的话,就是一次单条记录进行关联查询的。 
3、NESTED LOOP
driving table
可以用于(非等值,等值)连接,当where过滤后的记录数比较小时才会nested loops,where过滤后的记录数小的表为driving table。

通常要求驱动表的记录(符合条件的记录,通常通过高效的索引访问)较少,且被驱动表连接列有唯一索引或者选择性强的非唯一索引时,嵌套循环连接的效率是比较高的。

嵌套循环连接返回前几行的记录是非常快的,这是因为使用了嵌套循环后,不需要等到全部循环结束再返回结果集,而是不断地将查询出来的结果集返回。在这种情况下,终端用户将会快速地得到返回的首批记录,且同时等待Oracle内部处理其他记录并返回。如果查询的驱动表的记录数非常多,或者被驱动表的连接列上无索引或索引不是高度可选的情况,嵌套循环连接的效率是非常低的。

--sort merge join,结果集相对较大
在排序合并连接中是没有驱动表的概念的,两个互相连接的表按连接列的值先排序,排序完后形成的结果集再互相进行合并连接提取符合条件的记录。

可以用于(非等值,等值)连接。较大数据行,且为非等值连接时,用sort merge join,已经逐渐被hash join取代。

由于Oracle中排序操作的开销是非常消耗资源的,当结果集很大时排序合并连接的性能很差。
--hash join,结果集相对大
哈希连接分为两个阶段,如下。 
1、 构建阶段:优化器首先选择一张小表做为驱动表,运用哈希函数对连接列进行计算产生一张哈希表。通常这个步骤是在内存(hash_area_size)里面进行的,因此运算很快。 
2、 探测阶段:优化器对被驱动表的连接列运用同样的哈希函数计算得到的结果与前面形成的哈希表进行探测返回符合条件的记录。这个阶段中如果被驱动表的连接列的值没有与驱动表连接列的值相等的话,那么这些记录将会被丢弃而不进行探测。关于哈希连接更深层次的原理可以参考Itpub上网友logzgh发表的“hash join算法原理”帖子(http://www.itpub.net/showthread.php?threadid=315494)。 

哈希连接比较适用于返回大数据量结果集的连接。使用哈希连接必须是在CBO模式下,参数hash_join_enabled设置为true,且只适用于等值连接。

Hash join不需要在驱动表上存在索引。

从Oracle9i开始,哈希连接由于其良好的性能渐渐取代了原来的排序合并连接。

--跟表连接有关的几个HINT 
(1、)use_nl(t1,t2):表示对表t1、t2关联时采用嵌套循环连接。 
(2、)use_merge(t1,t2):表示对表t1、t2关联时采用排序合并连接。 
(3、)use_hash(t1,t2):表示对表t1、t2关联时采用哈希连接。 
(4、)leading(t):表示在进行表连接时,选择t为驱动表。 
(5、)ordred:要求优化器按from列出的表顺序进行连接。 

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/11990065/viewspace-731822/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/11990065/viewspace-731822/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值