楼主: newkid

[精华] [翻译]Oracle 12c优化器白皮书(完整版WORD文档已上传)

[复制链接]
论坛徽章:
1088
金色在线徽章
日期:2007-04-25 04:02:08金色在线徽章
日期:2007-06-29 04:02:43金色在线徽章
日期:2007-03-11 04:02:02在线时间
日期:2007-04-11 04:01:02在线时间
日期:2007-04-12 04:01:02在线时间
日期:2007-03-07 04:01:022008版在线时间
日期:2010-05-01 00:01:152008版在线时间
日期:2011-05-01 00:01:342008版在线时间
日期:2008-06-03 11:59:43ITPUB年度最佳技术原创精华奖
日期:2013-03-22 13:18:30
31#
发表于 2014-4-19 09:40 | 只看该作者
newkid 发表于 2014-4-19 02:23
达梦把这个叫平坦化。ORACLE会不会判断行间缓存的情况?如果有行间缓存,标量子查询有时候更合算。
下周 ...

有缓存的,包括FILTER,关联UPDATE。。。这些带:B1。。。的绑定变量的,都有缓存

当缓存起作用,可能效果比JOIN好。。。

使用道具 举报

回复
论坛徽章:
520
奥运会纪念徽章:垒球
日期:2008-09-15 01:28:12生肖徽章2007版:鸡
日期:2008-11-17 23:40:58生肖徽章2007版:马
日期:2008-11-18 05:09:48数据库板块每日发贴之星
日期:2008-11-29 01:01:02数据库板块每日发贴之星
日期:2008-12-05 01:01:03生肖徽章2007版:虎
日期:2008-12-10 07:47:462009新春纪念徽章
日期:2009-01-04 14:52:28数据库板块每日发贴之星
日期:2009-02-08 01:01:03生肖徽章2007版:蛇
日期:2009-03-09 22:18:532009日食纪念
日期:2009-07-22 09:30:00
32#
 楼主| 发表于 2014-4-23 07:51 | 只看该作者
完整版WORD附件已上传到一楼,修订了错别字。

使用道具 举报

回复
论坛徽章:
520
奥运会纪念徽章:垒球
日期:2008-09-15 01:28:12生肖徽章2007版:鸡
日期:2008-11-17 23:40:58生肖徽章2007版:马
日期:2008-11-18 05:09:48数据库板块每日发贴之星
日期:2008-11-29 01:01:02数据库板块每日发贴之星
日期:2008-12-05 01:01:03生肖徽章2007版:虎
日期:2008-12-10 07:47:462009新春纪念徽章
日期:2009-01-04 14:52:28数据库板块每日发贴之星
日期:2009-02-08 01:01:03生肖徽章2007版:蛇
日期:2009-03-09 22:18:532009日食纪念
日期:2009-07-22 09:30:00
33#
 楼主| 发表于 2014-4-25 03:50 | 只看该作者

下面就来试验“部分连接取值”特性(图29)。
在11G中设置了如下数据:

DESC SH.CUSTOMERS;

Name                         Null?    Type
---------------------------- -------- --------------------
CUST_ID                      NOT NULL NUMBER
CUST_FIRST_NAME              NOT NULL VARCHAR2(20)
CUST_LAST_NAME               NOT NULL VARCHAR2(40)
CUST_GENDER                  NOT NULL CHAR(1)
CUST_YEAR_OF_BIRTH           NOT NULL NUMBER(4)
CUST_MARITAL_STATUS                   VARCHAR2(20)
CUST_STREET_ADDRESS          NOT NULL VARCHAR2(40)
CUST_POSTAL_CODE             NOT NULL VARCHAR2(10)
CUST_CITY                    NOT NULL VARCHAR2(30)
CUST_CITY_ID                 NOT NULL NUMBER
CUST_STATE_PROVINCE          NOT NULL VARCHAR2(40)
CUST_STATE_PROVINCE_ID       NOT NULL NUMBER
COUNTRY_ID                   NOT NULL NUMBER
CUST_MAIN_PHONE_NUMBER       NOT NULL VARCHAR2(25)
CUST_INCOME_LEVEL                     VARCHAR2(30)
CUST_CREDIT_LIMIT                     NUMBER
CUST_EMAIL                            VARCHAR2(30)
CUST_TOTAL                   NOT NULL VARCHAR2(14)
CUST_TOTAL_ID                NOT NULL NUMBER
CUST_SRC_ID                           NUMBER
CUST_EFF_FROM                         DATE
CUST_EFF_TO                           DATE
CUST_VALID                            VARCHAR2(1)

jsu@JSU> SELECT COUNT(*) FROM SH.CUSTOMERS;

  COUNT(*)
----------
     55500
     
CREATE TABLE CUSTOMERS AS SELECT * FROM SH.CUSTOMERS;

ALTER TABLE CUSTOMERS ADD CONSTRAINT CUSTOMERS_PK PRIMARY KEY (CUST_ID);

CREATE TABLE ORDERS (order_id NUMBER, order_date DATE NOT NULL, amount NUMBER NOT NULL, cust_id NUMBER NOT NULL);

ALTER TABLE ORDERS ADD CONSTRAINT ORDERS_PK PRIMARY KEY (ORDER_ID);

ALTER TABLE ORDERS ADD CONSTRAINT ORDERS_CUST_ID_FK FOREIGN KEY (CUST_ID) REFERENCES CUSTOMERS(CUST_ID);

INSERT INTO ORDERS
SELECT n,SYSDATE-1000+n/10,n*10, cust_id
  FROM (SELECT LEVEL N FROM DUAL CONNECT BY LEVEL<=10000)
      ,(SELECT ROWNUM RN,cust_id FROM CUSTOMERS WHERE ROWNUM<=10000)
WHERE n=rn;
   
COMMIT;

EXEC DBMS_STATS.GATHER_TABLE_STATS(USER,'CUSTOMERS');
EXEC DBMS_STATS.GATHER_TABLE_STATS(USER,'ORDERS');

SET AUTOT TRACEONLY;

SELECT DISTINCT order_id
  FROM orders o, customers c
WHERE o.cust_id = c.cust_id
       AND order_id < 2400;


Execution Plan
----------------------------------------------------------
Plan hash value: 286617579

------------------------------------------------------------------------------
| Id  | Operation        | Name      | Rows  | Bytes | Cost (%CPU)| Time     |
------------------------------------------------------------------------------
|   0 | SELECT STATEMENT |           |  2399 |  9596 |     6   (0)| 00:00:01 |
|*  1 |  INDEX RANGE SCAN| ORDERS_PK |  2399 |  9596 |     6   (0)| 00:00:01 |
------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - access("ORDER_ID"<2400)

可见,不但没有SORT UNIQUE, 连HASH JOIN也没有,甚至都没有扫描CUSTOMER表!因为我们有外键,CBO知道这个连接不会改变行数。所以我说这个例子举得不好,DISTINT 以及JOIN都是多余的。

把ORDERS.CUST_ID上的非空约束去掉:

ALTER TABLE ORDERS MODIFY CUST_ID NULL;

再来看计划:

Execution Plan
----------------------------------------------------------
Plan hash value: 1275100350

----------------------------------------------------------------------------
| Id  | Operation         | Name   | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |        |  2399 | 19192 |    13   (0)| 00:00:01 |
|*  1 |  TABLE ACCESS FULL| ORDERS |  2399 | 19192 |    13   (0)| 00:00:01 |
----------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - filter("ORDER_ID"<2400 AND "O"."CUST_ID" IS NOT NULL)
   
CBO还是很聪明,没有JOIN, 只是多了个AND "O"."CUST_ID" IS NOT NULL的过滤谓词,因为外键还在。

把外键去掉:
ALTER TABLE ORDERS DROP CONSTRAINT ORDERS_CUST_ID_FK;

Execution Plan
----------------------------------------------------------
Plan hash value: 2416930460

------------------------------------------------------------------------------------
| Id  | Operation           | Name         | Rows  | Bytes | Cost (%CPU)| Time     |
------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT    |              |  2399 | 31187 |    14   (8)| 00:00:01 |
|   1 |  HASH UNIQUE        |              |  2399 | 31187 |    14   (8)| 00:00:01 |
|   2 |   NESTED LOOPS      |              |  2399 | 31187 |    13   (0)| 00:00:01 |
|*  3 |    TABLE ACCESS FULL| ORDERS       |  2399 | 19192 |    13   (0)| 00:00:01 |
|*  4 |    INDEX UNIQUE SCAN| CUSTOMERS_PK |     1 |     5 |     0   (0)| 00:00:01 |
------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   3 - filter("ORDER_ID"<2400)
   4 - access("O"."CUST_ID"="C"."CUST_ID")

这时没有外键,不能确定ORDERS.CUST_ID是一个有效的ID, CBO只好做了连接,用的是NESTED LOOPS。不知道为什么还有HASH UNIQUE, 明明不需要去重。如果把这个完全多余的 DISTINCT 拿掉,这个HASH UNIQUE就消失了。CBO还是不够聪明。


去掉CUSTOMERS上的唯一索引(此时DISTINCT就不再多余了):

ALTER TABLE CUSTOMERS DROP CONSTRAINT CUSTOMERS_PK;

终于得到图29中的计划:
Execution Plan
----------------------------------------------------------
Plan hash value: 358993716

---------------------------------------------------------------------------------
| Id  | Operation           | Name      | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------------
|   0 | SELECT STATEMENT    |           |  2399 | 31187 |   420   (1)| 00:00:06 |
|   1 |  HASH UNIQUE        |           |  2399 | 31187 |   420   (1)| 00:00:06 |
|*  2 |   HASH JOIN         |           |  2399 | 31187 |   419   (1)| 00:00:06 |
|*  3 |    TABLE ACCESS FULL| ORDERS    |  2399 | 19192 |    13   (0)| 00:00:01 |
|   4 |    TABLE ACCESS FULL| CUSTOMERS | 55500 |   270K|   405   (1)| 00:00:05 |
---------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   2 - access("O"."CUST_ID"="C"."CUST_ID")
   3 - filter("ORDER_ID"<2400)

把索引加回去,只是不再唯一:
CREATE INDEX CUSTOMERS_IDX ON CUSTOMERS(CUST_ID);


Execution Plan
----------------------------------------------------------
Plan hash value: 3716455140

----------------------------------------------------------------------------------------
| Id  | Operation              | Name          | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT       |               |  2399 | 31187 |    50   (4)| 00:00:01 |
|   1 |  HASH UNIQUE           |               |  2399 | 31187 |    50   (4)| 00:00:01 |
|*  2 |   HASH JOIN            |               |  2399 | 31187 |    49   (3)| 00:00:01 |
|*  3 |    TABLE ACCESS FULL   | ORDERS        |  2399 | 19192 |    13   (0)| 00:00:01 |
|   4 |    INDEX FAST FULL SCAN| CUSTOMERS_IDX | 55500 |   270K|    35   (0)| 00:00:01 |
----------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   2 - access("O"."CUST_ID"="C"."CUST_ID")
   3 - filter("ORDER_ID"<2400)

此时的全表扫描变成了全索引扫描,这是把索引当作瘦表来用了。

把整个试验在12C中做一遍,当把ORDERS上的外键拿掉之后,计划变成:

Execution Plan
----------------------------------------------------------
Plan hash value: 2121488774

------------------------------------------------------------------------------------
| Id  | Operation           | Name         | Rows  | Bytes | Cost (%CPU)| Time     |
------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT    |              |  2399 | 31187 |    13   (0)| 00:00:01 |
|   1 |  HASH UNIQUE        |              |  2399 | 31187 |    13   (0)| 00:00:01 |
|   2 |   NESTED LOOPS SEMI |              |  2399 | 31187 |    13   (0)| 00:00:01 |
|*  3 |    TABLE ACCESS FULL| ORDERS       |  2399 | 19192 |    13   (0)| 00:00:01 |
|*  4 |    INDEX UNIQUE SCAN| CUSTOMERS_PK | 55500 |   270K|     0   (0)| 00:00:01 |
------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   3 - filter("ORDER_ID"<2400)
   4 - access("O"."CUST_ID"="C"."CUST_ID")

11g中的NESTED LOOPS变成了NESTED LOOPS SEMI, 这就是新特性在起作用了。随后的两个测试中的HASH JOIN 也变成了HASH JOIN SEMI。但是那个HASH UNIQUE还在,难道CBO没看到ORDER_ID是唯一的吗?




使用道具 举报

回复
论坛徽章:
59
2013年新春福章
日期:2013-02-25 11:02:12双鱼座
日期:2015-07-31 08:13:07秀才
日期:2015-08-24 09:44:20秀才
日期:2015-08-24 09:51:48秀才
日期:2015-10-19 15:50:39ITPUB14周年纪念章
日期:2015-10-26 17:23:44秀才
日期:2015-11-30 09:59:23秀才
日期:2015-12-14 15:02:13秀才
日期:2015-12-21 09:48:11秀才
日期:2016-01-21 13:37:04
34#
发表于 2014-4-25 08:30 | 只看该作者
学习

使用道具 举报

回复
论坛徽章:
58
生肖徽章2007版:马
日期:2009-11-06 23:12:33授权会员
日期:2013-01-10 14:38:592013年新春福章
日期:2013-02-25 14:51:24马自达
日期:2013-08-07 10:54:45红旗
日期:2013-08-09 13:48:48劳斯莱斯
日期:2013-09-12 15:56:37萤石
日期:2013-10-31 08:44:19优秀写手
日期:2013-12-18 09:29:13Jeep
日期:2014-01-14 10:53:432014年新春福章
日期:2014-02-18 16:43:09
35#
发表于 2014-4-28 22:18 | 只看该作者

使用道具 举报

回复
论坛徽章:
8
2010新春纪念徽章
日期:2010-03-01 11:19:53ITPUB十周年纪念徽章
日期:2011-11-01 16:23:26鲜花蛋
日期:2012-03-24 09:28:42ITPUB 11周年纪念徽章
日期:2012-10-09 18:08:15ITPUB 11周年纪念徽章
日期:2012-10-23 16:55:312013年新春福章
日期:2013-02-25 14:51:24日产
日期:2013-10-24 08:12:112014年世界杯参赛球队: 尼日利亚
日期:2014-07-24 11:03:13
36#
发表于 2014-5-1 22:32 | 只看该作者
占位学习

使用道具 举报

回复
论坛徽章:
26
2011新春纪念徽章
日期:2011-02-18 11:43:34马上有房
日期:2014-02-18 16:42:02问答徽章
日期:2014-04-14 17:58:34马上有车
日期:2014-10-11 12:20:37马上有钱
日期:2014-11-17 11:02:102015年新春福章
日期:2015-03-04 14:51:122015年新春福章
日期:2015-03-06 11:57:31暖羊羊
日期:2015-05-19 13:53:31暖羊羊
日期:2015-06-17 17:19:26暖羊羊
日期:2015-07-07 11:02:48
37#
发表于 2014-5-4 16:49 | 只看该作者
Thanks for your sharing

使用道具 举报

回复
求职 : 数据库管理员
论坛徽章:
45
祖国60周年纪念徽章
日期:2015-05-19 13:02:04itpub13周年纪念徽章
日期:2014-12-30 09:02:122010数据库技术大会纪念徽章
日期:2015-04-23 10:33:192011数据库大会纪念章
日期:2015-04-23 10:33:192012数据库大会纪念章
日期:2015-04-23 10:33:192013数据库大会纪念章
日期:2015-04-23 10:33:192014数据库大会纪念章
日期:2015-04-23 10:33:192015中国数据库技术大会纪念徽章
日期:2015-04-24 16:04:24暖羊羊
日期:2015-05-13 18:24:182015年新春福章
日期:2015-05-30 17:02:05
38#
发表于 2014-6-16 21:43 | 只看该作者

使用道具 举报

回复
论坛徽章:
9
2013年新春福章
日期:2013-02-25 14:51:24灰彻蛋
日期:2013-02-28 17:57:18蜘蛛蛋
日期:2013-03-06 17:16:15茶鸡蛋
日期:2013-03-26 17:32:46雪佛兰
日期:2013-11-26 10:47:53优秀写手
日期:2014-01-22 06:00:12马上有车
日期:2014-04-16 17:19:19慢羊羊
日期:2015-03-04 14:53:332015年新春福章
日期:2015-03-06 11:58:39
39#
发表于 2014-7-1 17:21 | 只看该作者
newkid 发表于 2014-4-17 21:38
乱用成语,这两个意思是反的。

应该是篡改成语,改后意思应该是一样的

使用道具 举报

回复
论坛徽章:
4
大众
日期:2013-12-29 09:16:37优秀写手
日期:2013-12-18 09:29:112014年新春福章
日期:2014-02-18 16:49:31马上有钱
日期:2014-02-18 16:49:31
40#
发表于 2014-11-3 14:27 | 只看该作者
太牛X了,速度不是一般的快啊

使用道具 举报

回复

您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

TOP技术积分榜 社区积分榜 徽章 团队 统计 知识索引树 积分竞拍 文本模式 帮助
  ITPUB首页 | ITPUB论坛 | 数据库技术 | 企业信息化 | 开发技术 | 微软技术 | 软件工程与项目管理 | IBM技术园地 | 行业纵向讨论 | IT招聘 | IT文档
  ChinaUnix | ChinaUnix博客 | ChinaUnix论坛
CopyRight 1999-2011 itpub.net All Right Reserved. 北京盛拓优讯信息技术有限公司版权所有 联系我们 未成年人举报专区 
京ICP备16024965号-8  北京市公安局海淀分局网监中心备案编号:11010802021510 广播电视节目制作经营许可证:编号(京)字第1149号
  
快速回复 返回顶部 返回列表