楼主: oradbHome

性能调整 order by 和 rownum 导致执行计划改变.附录10053

[复制链接]
招聘 : Java研发
论坛徽章:
71
马上加薪
日期:2014-02-19 11:55:14蜘蛛蛋
日期:2012-12-26 18:16:01茶鸡蛋
日期:2012-11-16 08:12:48ITPUB 11周年纪念徽章
日期:2012-10-09 18:05:07奥运会纪念徽章:网球
日期:2012-08-23 14:58:08奥运会纪念徽章:沙滩排球
日期:2012-07-19 17:28:14版主2段
日期:2012-07-07 02:21:02咸鸭蛋
日期:2012-03-23 18:17:482012新春纪念徽章
日期:2012-02-13 15:13:512012新春纪念徽章
日期:2012-02-13 15:13:51
11#
发表于 2009-1-8 10:17 | 只看该作者
原帖由 oradbHome 于 2009-1-8 09:05 发表


这个order by sort 是整个的排序所需要的cost . 但是应该是根据条件 p.ownerid = '123' 在过滤完后,在进行排序的.

总之oracle 选择的这样的执行计划是错误的. 而我的统计信息也是相对准确的.


CBO选择了错误的执行计划和CBO选择了cost高的执行计划,这个差别太大了

很简单,你hint 让他走你想走的索引,看其总的cost就行了

使用道具 举报

回复
论坛徽章:
97
ITPUB元老
日期:2008-06-30 12:48:39暖羊羊
日期:2015-03-04 14:50:372015年新春福章
日期:2015-03-06 11:57:312010数据库技术大会纪念徽章
日期: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:19林肯
日期:2013-10-31 12:31:382013年新春福章
日期:2013-02-25 14:51:24
12#
 楼主| 发表于 2009-1-8 10:27 | 只看该作者
我刚才做的测试. 我的测试.在where条件中的顺序可以和复合index 的顺序不一致.
这个的index 可以适合更多的查询. 但是对我上面的sql 是不适合的. 但是应该用到 INDEX SKIP SCAN .

棉花 ,但是有rownum . orader 这样的条件下 oracle 选择了错误的执行计划.来怎么避免呢?

test@stat.r> create table tab as select * from dba_objects;

表已创建。

test@stat.r> CREATE INDEX ind_tab_ot ON tab(owner ,last_ddl_time);

索引已创建。

test@stat.r> SELECT * FROM tab t WHERE  T.LAST_DDL_TIME > SYSDate AND t.owner='SYS';

执行计划
----------------------------------------------------------
Plan hash value: 2269374563

------------------------------------------------------------------------------------------
| Id  | Operation                   | Name       | Rows  | Bytes | Cost (%CPU)| Time     |
------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |            |     1 |   177 |     1   (0)| 00:00:01 |
|   1 |  TABLE ACCESS BY INDEX ROWID| TAB        |     1 |   177 |     1   (0)| 00:00:01 |
|*  2 |   INDEX RANGE SCAN          | IND_TAB_OT |     1 |       |     1   (0)| 00:00:01 |
------------------------------------------------------------------------------------------

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

   2 - access("T"."OWNER"='SYS' AND "T"."LAST_DDL_TIME">SYSDATE@! AND
              "T"."LAST_DDL_TIME" IS NOT NULL)

Note
-----
   - dynamic sampling used for this statement

test@stat.r> SELECT * FROM tab t WHERE t.owner='SYS' and  T.LAST_DDL_TIME > SYSDate ;

执行计划
----------------------------------------------------------
Plan hash value: 2269374563

------------------------------------------------------------------------------------------
| Id  | Operation                   | Name       | Rows  | Bytes | Cost (%CPU)| Time     |
------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |            |     1 |   177 |     1   (0)| 00:00:01 |
|   1 |  TABLE ACCESS BY INDEX ROWID| TAB        |     1 |   177 |     1   (0)| 00:00:01 |
|*  2 |   INDEX RANGE SCAN          | IND_TAB_OT |     1 |       |     1   (0)| 00:00:01 |
------------------------------------------------------------------------------------------

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

   2 - access("T"."OWNER"='SYS' AND "T"."LAST_DDL_TIME">SYSDATE@! AND
              "T"."LAST_DDL_TIME" IS NOT NULL)

Note
-----
   - dynamic sampling used for this statement

使用道具 举报

回复
论坛徽章:
138
19周年集字徽章-19
日期:2020-06-08 08:30:56马上加薪
日期:2014-02-19 11:55:14马上有对象
日期:2014-02-19 11:55:14马上有钱
日期:2014-02-19 11:55:14马上有房
日期:2014-02-19 11:55:14马上有车
日期:2014-02-19 11:55:14马上有房
日期:2014-02-18 16:42:022014年新春福章
日期:2014-02-18 16:42:02路虎
日期:2013-11-22 12:26:18问答徽章
日期:2014-05-08 12:15:31
13#
发表于 2009-1-8 10:30 | 只看该作者
我没明白你的实验要说明个什么问题,你的索引是一个索引,只是你where里的顺序不一样而已,where中条件的顺序是不会对cbo造成影响的

使用道具 举报

回复
论坛徽章:
138
19周年集字徽章-19
日期:2020-06-08 08:30:56马上加薪
日期:2014-02-19 11:55:14马上有对象
日期:2014-02-19 11:55:14马上有钱
日期:2014-02-19 11:55:14马上有房
日期:2014-02-19 11:55:14马上有车
日期:2014-02-19 11:55:14马上有房
日期:2014-02-18 16:42:022014年新春福章
日期:2014-02-18 16:42:02路虎
日期:2013-11-22 12:26:18问答徽章
日期:2014-05-08 12:15:31
14#
发表于 2009-1-8 10:30 | 只看该作者

回复 #12 oradbHome 的帖子

我觉得分页这样的语句可以试试用hint固定住

使用道具 举报

回复
论坛徽章:
97
ITPUB元老
日期:2008-06-30 12:48:39暖羊羊
日期:2015-03-04 14:50:372015年新春福章
日期:2015-03-06 11:57:312010数据库技术大会纪念徽章
日期: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:19林肯
日期:2013-10-31 12:31:382013年新春福章
日期:2013-02-25 14:51:24
15#
 楼主| 发表于 2009-1-8 10:32 | 只看该作者
原帖由 anlinew 于 2009-1-8 10:17 发表


CBO选择了错误的执行计划和CBO选择了cost高的执行计划,这个差别太大了

很简单,你hint 让他走你想走的索引,看其总的cost就行了


按照cost 来说 ,oracle 是选择了正确执行计划了.
这说明cbo 计算出来的cost 信息有问题,这也就说明了统计信息不准确, 但是现在不确定是那部分统计信息不准确.

使用道具 举报

回复
论坛徽章:
97
ITPUB元老
日期:2008-06-30 12:48:39暖羊羊
日期:2015-03-04 14:50:372015年新春福章
日期:2015-03-06 11:57:312010数据库技术大会纪念徽章
日期: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:19林肯
日期:2013-10-31 12:31:382013年新春福章
日期:2013-02-25 14:51:24
16#
 楼主| 发表于 2009-1-8 10:33 | 只看该作者
原帖由 棉花糖ONE 于 2009-1-8 10:30 发表
我没明白你的实验要说明个什么问题,你的索引是一个索引,只是你where里的顺序不一样而已,where中条件的顺序是不会对cbo造成影响的



这是我原来理解错误了.我原来一直以为 复合index 的顺序 要 和where 条件的中顺序一样的. 如果不一样是不能使用复合index 的.

使用道具 举报

回复
论坛徽章:
138
19周年集字徽章-19
日期:2020-06-08 08:30:56马上加薪
日期:2014-02-19 11:55:14马上有对象
日期:2014-02-19 11:55:14马上有钱
日期:2014-02-19 11:55:14马上有房
日期:2014-02-19 11:55:14马上有车
日期:2014-02-19 11:55:14马上有房
日期:2014-02-18 16:42:022014年新春福章
日期:2014-02-18 16:42:02路虎
日期:2013-11-22 12:26:18问答徽章
日期:2014-05-08 12:15:31
17#
发表于 2009-1-8 10:40 | 只看该作者
你这语句是owner_id为某个值的,然后按照change_time升序排序得到前10个最大的,如果创建(change_time,owner_id)的索引是没意义的,按照这个复合索引的定义,change_time相同的按照owner_id排序,而(owner_id,change_time)这个索引是owner_id相同的按照change_time排序,这个索引的顺序和你要返回结果的顺序一致,所以这个索引就ok了

使用道具 举报

回复
论坛徽章:
97
ITPUB元老
日期:2008-06-30 12:48:39暖羊羊
日期:2015-03-04 14:50:372015年新春福章
日期:2015-03-06 11:57:312010数据库技术大会纪念徽章
日期: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:19林肯
日期:2013-10-31 12:31:382013年新春福章
日期:2013-02-25 14:51:24
18#
 楼主| 发表于 2009-1-8 10:41 | 只看该作者
原帖由 棉花糖ONE 于 2009-1-8 10:30 发表
我觉得分页这样的语句可以试试用hint固定住


一般会在分页中使用 /*+ first_rows */ , 还有这样的sql 是不确定的. 是根据用户选择的条件组合出来的sql.

使用道具 举报

回复
论坛徽章:
97
ITPUB元老
日期:2008-06-30 12:48:39暖羊羊
日期:2015-03-04 14:50:372015年新春福章
日期:2015-03-06 11:57:312010数据库技术大会纪念徽章
日期: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:19林肯
日期:2013-10-31 12:31:382013年新春福章
日期:2013-02-25 14:51:24
19#
 楼主| 发表于 2009-1-8 10:45 | 只看该作者
原帖由 棉花糖ONE 于 2009-1-8 10:40 发表
你这语句是owner_id为某个值的,然后按照change_time升序排序得到前10个最大的,如果创建(change_time,owner_id)的索引是没意义的,按照这个复合索引的定义,change_time相同的按照owner_id排序,而(owner_id,change_time)这个索引是owner_id相同的按照change_time排序,这个索引的顺序和你要返回结果的顺序一致,所以这个索引就ok了


如果是按照 change_time desc , 那就建立(owner_id,change_time desc) 这样的index 会好吗?

使用道具 举报

回复
论坛徽章:
138
19周年集字徽章-19
日期:2020-06-08 08:30:56马上加薪
日期:2014-02-19 11:55:14马上有对象
日期:2014-02-19 11:55:14马上有钱
日期:2014-02-19 11:55:14马上有房
日期:2014-02-19 11:55:14马上有车
日期:2014-02-19 11:55:14马上有房
日期:2014-02-18 16:42:022014年新春福章
日期:2014-02-18 16:42:02路虎
日期:2013-11-22 12:26:18问答徽章
日期:2014-05-08 12:15:31
20#
发表于 2009-1-8 10:46 | 只看该作者
原帖由 oradbHome 于 2009-1-8 10:45 发表


如果是按照 change_time desc , 那就建立(owner_id,change_time desc) 这样的index 会好吗?


使用道具 举报

回复

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

本版积分规则 发表回复

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