楼主: myownstars

一次针对Not in的优化--如何让其选择hash join anti

[复制链接]
论坛徽章:
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
11#
发表于 2011-5-22 17:14 | 只看该作者


not in 和not exitst在处理的差异主要是处理null上

filte其实体现了些

不过如ding所说

这个差异改进和优化在11g中实现了

使用道具 举报

回复
论坛徽章:
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
12#
发表于 2011-5-22 17:22 | 只看该作者
关键是myownstars 掘的比较深

呵呵

使用道具 举报

回复
论坛徽章:
86
2015中国数据库技术大会纪念徽章
日期:2015-04-24 16:04:24马上有车
日期:2014-02-19 11:55:14马上有车
日期:2014-02-18 16:41:112014年新春福章
日期:2014-02-18 16:41:11优秀写手
日期:2013-12-18 09:29:11日产
日期:2013-10-17 08:44:39马自达
日期:2013-08-26 16:28:022013年新春福章
日期:2013-02-25 14:51:24ITPUB 11周年纪念徽章
日期:2012-10-23 16:55:51马上有房
日期:2014-02-19 11:55:14
13#
发表于 2011-5-23 11:25 | 只看该作者
排版有点乱,建议修改一下,看着更方便,楼主的注释应该高亮。

使用道具 举报

回复
论坛徽章:
41
马上加薪
日期:2014-02-19 11:55:14铁扇公主
日期:2012-02-21 15:02:402012新春纪念徽章
日期:2012-02-13 15:12:092012新春纪念徽章
日期:2012-02-13 15:12:092012新春纪念徽章
日期:2012-02-13 15:12:092012新春纪念徽章
日期:2012-02-13 15:12:092012新春纪念徽章
日期:2012-02-13 15:12:092012新春纪念徽章
日期:2012-01-04 11:50:44ITPUB十周年纪念徽章
日期:2011-11-01 16:21:15ITPUB年度最佳BLOG写作奖
日期:2012-03-13 17:09:53
14#
发表于 2011-5-23 14:34 | 只看该作者
这个帖子的版式之所以乱是因为执行计划中的分割线过长。
我尝试对主帖进行了调整。

建议大家以后贴执行计划时选择“宋体”,这样执行计划将更具可读性。

secooler

使用道具 举报

回复
论坛徽章:
10
2011新春纪念徽章
日期:2011-02-18 11:43:342015年新春福章
日期:2015-03-06 11:58:18懒羊羊
日期:2015-03-04 14:52:11马上有钱
日期:2014-02-18 16:43:092014年新春福章
日期:2014-02-18 16:43:09优秀写手
日期:2013-12-18 09:29:11三菱
日期:2013-08-30 20:37:412013年新春福章
日期:2013-02-25 14:51:24ITPUB十周年纪念徽章
日期:2011-11-01 16:24:51暖羊羊
日期:2015-06-22 15:51:36
15#
 楼主| 发表于 2011-5-23 14:40 | 只看该作者

回复 #14 secooler 的帖子

已对板式进行调整 看起来舒服了一点

使用道具 举报

回复
论坛徽章:
0
16#
发表于 2011-5-23 16:23 | 只看该作者
不错

使用道具 举报

回复
论坛徽章:
20
马上有钱
日期:2014-03-05 18:13:002013年新春福章
日期:2013-02-25 14:51:24ITPUB 11周年纪念徽章
日期:2012-10-09 18:05:072012新春纪念徽章
日期:2012-01-04 11:49:54ITPUB十周年纪念徽章
日期:2011-11-01 16:19:41迷宫蛋
日期:2011-11-07 14:46:51茶鸡蛋
日期:2011-07-11 20:36:00咸鸭蛋
日期:2011-06-30 15:11:57辩论纪念章
日期:2010-11-15 09:41:552010广州亚运会纪念徽章:网球
日期:2011-05-11 14:11:47
17#
发表于 2011-5-27 14:18 | 只看该作者
marked and practise it later. thanks LZ

使用道具 举报

回复
论坛徽章:
8
数据库板块每日发贴之星
日期:2009-06-12 01:01:02数据库板块每日发贴之星
日期:2009-06-21 01:01:01ITPUB9周年纪念徽章
日期:2010-10-08 09:32:272010广州亚运会纪念徽章:游泳
日期:2010-11-12 16:42:092011新春纪念徽章
日期:2011-02-18 11:42:502010广州亚运会纪念徽章:三项全能
日期:2011-02-26 13:07:50咸鸭蛋
日期:2011-08-30 15:51:05ITPUB十周年纪念徽章
日期:2011-11-01 16:25:22
18#
发表于 2011-8-29 16:30 | 只看该作者
Query1:select department_name
        from hr.departments dept
        where department_id NOT IN
                   (select department_id from hr.employees emp);
---------------------------------------------------------------------------------------------
| Id  | Operation                                     | Name             | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                       |                       |    16 |   304 |     6  (17)| 00:00:01 |
|   1 |  MERGE JOIN ANTI NA                    |                        |    16 |   304 |     6  (17)| 00:00:01 |
|   2 |   SORT JOIN                                   |                        |    27 |   432 |     2   (0)| 00:00:01 |
|   3 |    TABLE ACCESS BY INDEX ROWID| DEPARTMENTS |    27 |   432 |     2   (0)| 00:00:01 |
|   4 |     INDEX FULL SCAN                      | DEPT_ID_PK   |    27 |           |     1   (0)| 00:00:01 |
|*  5 |   SORT UNIQUE                             |                       |   107 |   321 |     4  (25)| 00:00:01 |
|   6 |    TABLE ACCESS FULL                   | EMPLOYEES    |   107 |   321 |     3   (0)| 00:00:01 |
---------------------------------------------------------------------------------------------

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

   5 - access("DEPARTMENT_ID"="DEPARTMENT_ID")
       filter("DEPARTMENT_ID"="DEPARTMENT_ID")
no rows selected

Query2:select department_name
       from hr.departments dept
       where NOT EXISTS (select null from hr.employees emp
       where emp.department_id = dept.department_id);
----------------------------------------------------------------------------------------
| Id  | Operation                   | Name                          | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT     |                                    |    16 |   304 |     3   (0)| 00:00:01 |
|   1 |  NESTED LOOPS ANTI  |                                     |    16 |   304 |     3   (0)| 00:00:01 |
|   2 |   TABLE ACCESS FULL  | DEPARTMENTS             |    27 |   432 |     3   (0)| 00:00:01 |
|*  3 |   INDEX RANGE SCAN  | EMP_DEPARTMENT_IX |    44 |   132 |     0   (0)| 00:00:01 |
----------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------

   3 - access("EMP"."DEPARTMENT_ID"="DEPT"."DEPARTMENT_ID")

16 rows selected.

select count(*) from employees where department_id is null;

  COUNT(*)
----------
         1

11g里面因为employments的column department_id有null值,所以not in返回错误结果。
添加is not null后问题解决。
Query3: select department_name
        from hr.departments dept
        where department_id NOT IN (select department_id from hr.employees emp
        where department_id is not null);
----------------------------------------------------------------------------------------
| Id  | Operation                     | Name                       | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT     |                                   |    16 |   304 |     3   (0)| 00:00:01 |
|   1 |  NESTED LOOPS ANTI  |                                    |    16 |   304 |     3   (0)| 00:00:01 |
|   2 |   TABLE ACCESS FULL | DEPARTMENTS             |    27 |   432 |     3   (0)| 00:00:01 |
|*  3 |   INDEX RANGE SCAN | EMP_DEPARTMENT_IX |    43 |   129 |     0   (0)| 00:00:01 |
----------------------------------------------------------------------------------------
16 rows selected.


Query4:select /* NOT IN */ department_name
        from hr.departments dept
        where NVL(department_id,'NULL') NOT IN
        (select department_id from hr.employees emp);

no rows selected
--------------------------------------------------------------------------------------------
| Id  | Operation              | Name              | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT       |                   |     1 |    19 |     6   (0)| 00:00:01 |
|*  1 |  FILTER                |                   |       |       |            |          |
|   2 |   NESTED LOOPS ANTI SNA|                   |    25 |   475 |     6  (50)| 00:00:01 |
|   3 |    TABLE ACCESS FULL   | DEPARTMENTS       |    27 |   432 |     3   (0)| 00:00:01 |
|*  4 |    INDEX RANGE SCAN    | EMP_DEPARTMENT_IX |    10 |    30 |     0   (0)| 00:00:01 |
|*  5 |   TABLE ACCESS FULL    | EMPLOYEES         |     1 |     6 |     3   (0)| 00:00:01 |
--------------------------------------------------------------------------------------------

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

   1 - filter( NOT EXISTS (SELECT 0 FROM "HR"."EMPLOYEES" "EMP" WHERE
              "DEPARTMENT_ID" IS NULL))
   4 - access("DEPARTMENT_ID"=NVL("DEPARTMENT_ID",TO_NUMBER('NULL')))
   5 - filter("DEPARTMENT_ID" IS NULL)

Query1和Query4都是没有结果返回。其实这样的情况下:
1,为该列加not null约束
2,改写sql,如not exists
3,where 列添加is not null

[ 本帖最后由 Coast_lichao 于 2011-8-29 16:38 编辑 ]

Not in Try.txt

5.15 KB, 下载次数: 6

使用道具 举报

回复
论坛徽章:
5
ITPUB9周年纪念徽章
日期:2010-10-08 09:28:51数据库板块每日发贴之星
日期:2011-07-22 01:01:02蜘蛛蛋
日期:2011-08-24 14:10:13ITPUB十周年纪念徽章
日期:2011-11-01 16:24:042012新春纪念徽章
日期:2012-01-04 11:54:26
19#
发表于 2011-8-30 00:10 | 只看该作者
原帖由 dingjun123 于 2011-5-20 21:34 发表
11g有null aware anti join了,不过还是anti join最好


呵呵 兔子哥 null aware anti join 在11gR1 上有BUG 导致ORA-600 ,赞同使用anti join
其实not null的确是个问题,有时候有not null 就是不走索引

使用道具 举报

回复
论坛徽章:
13
2013年新春福章
日期:2013-04-08 17:42:48技术图书徽章
日期:2014-05-13 10:11:54马上有对象
日期:2014-02-18 16:44:08ITPUB社区12周年站庆徽章
日期:2013-10-17 13:56:392013年新春福章
日期:2013-06-05 15:29:212013年新春福章
日期:2013-06-05 15:29:212013年新春福章
日期:2013-06-05 15:29:212013年新春福章
日期:2013-05-27 10:23:002013年新春福章
日期:2013-05-27 10:23:002013年新春福章
日期:2013-05-27 10:23:00
20#
发表于 2013-5-9 16:02 | 只看该作者
本帖最后由 边-城 于 2013-5-9 16:03 编辑

到了11g这两种写法执行计划应该一样了,都是hash join anti,无论连接列是否设为not null

使用道具 举报

回复

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

本版积分规则 发表回复

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