楼主: 伊思

[讨论] is not null和<>如何走索引

[复制链接]
论坛徽章:
4
ITPUB十周年纪念徽章
日期:2011-11-01 16:24:51灰彻蛋
日期:2011-11-07 07:32:08蛋疼蛋
日期:2011-12-26 14:19:11蛋疼蛋
日期:2012-04-07 01:24:00
11#
发表于 2011-11-1 13:01 | 只看该作者
likgui 发表于 2011-10-31 21:46
create index ind on t(col1 ,0)就可以了。


likgui 说的方案可以。
   
下面是我的实验过程。

建两个表,test表在CNT列上做了一个NULL的索引,testX表则CNT列上没有定义索引。
当同是执行 “where cnt is not null”条件时,test走了索引,而textX走的是全表扫描。

select * from testX where cnt is not null
select * from test where cnt is not null


【建表】
-- Create table
create table TEST
(
  ID  NUMBER,
  CNT NUMBER,
  C1  VARCHAR2(10),
  C2  VARCHAR2(10)
)
;
-- Create/Recreate indexes
create index IDX_TEST on TEST (CNT, 0)
;



-- Create table
create table TESTX
(
  ID  NUMBER,
  CNT NUMBER,
  C1  VARCHAR2(10),
  C2  VARCHAR2(10)
)
;


【表中数据】
SQL> select * from testx;

        ID        CNT C1         C2
---------- ---------- ---------- ----------
         1          3 aa         aaa
         2            bb         bbb
         3          4 bb         bbb
         4            bb         bbb
         5            bb         bbb
         6          5 bb         bbb
         7            bb         bbb
         8          6 bb         bbb
         9          7 bb         bbb

9 rows selected

SQL>

SQL> select * from test;

        ID        CNT C1         C2
---------- ---------- ---------- ----------
         1          3 aa         aaa
         2            bb         bbb
         3          4 bb         bbb
         4            bb         bbb
         5            bb         bbb
         6          5 bb         bbb
         7            bb         bbb
         8          6 bb         bbb
         9          7 bb         bbb

9 rows selected

SQL>


【执行计划 testX表】
select * from testX where cnt is not null

SELECT STATEMENT, GOAL = ALL_ROWS                        Cost=3        Cardinality=5        Bytes=200
TABLE ACCESS FULL        Object owner=SCOTT        Object name=TESTX        Cost=3        Cardinality=5        Bytes=200

【执行计划 test表】
select * from test where cnt is not null

SELECT STATEMENT, GOAL = ALL_ROWS                        Cost=2        Cardinality=5        Bytes=200
TABLE ACCESS BY INDEX ROWID        Object owner=SCOTT        Object name=TEST        Cost=2        Cardinality=5        Bytes=200
  INDEX FULL SCAN        Object owner=SCOTT        Object name=IDX_TEST        Cost=1        Cardinality=1       

使用道具 举报

回复
论坛徽章:
194
红宝石
日期:2014-05-09 08:24:37萤石
日期:2014-01-03 10:25:39奥运会纪念徽章:羽毛球
日期:2008-07-01 10:46:06奥运会纪念徽章:马术
日期:2008-07-07 17:43:24奥运会纪念徽章:射箭
日期:2008-07-25 18:07:39奥运会纪念徽章:皮划艇激流回旋
日期:2008-07-30 10:02:57奥运会纪念徽章:花样游泳
日期:2008-09-26 13:02:43奥运会纪念徽章:排球
日期:2008-12-03 11:23:272010新春纪念徽章
日期:2010-01-04 08:33:082010年世界杯参赛球队:澳大利亚
日期:2010-02-26 11:08:44
12#
发表于 2011-11-1 14:32 | 只看该作者
create table t as select rownum id,'test' name from dual connect by level <=1;
insert into  t  select rownum+1 id,NULL name from dual connect by level <=9999;
commit;
create index i_t_name on t(name);
exec DBMS_STATS.GATHER_TABLE_STATS (user,'T', method_opt=>'FOR ALL columns size 1 ')



使用道具 举报

回复
论坛徽章:
194
红宝石
日期:2014-05-09 08:24:37萤石
日期:2014-01-03 10:25:39奥运会纪念徽章:羽毛球
日期:2008-07-01 10:46:06奥运会纪念徽章:马术
日期:2008-07-07 17:43:24奥运会纪念徽章:射箭
日期:2008-07-25 18:07:39奥运会纪念徽章:皮划艇激流回旋
日期:2008-07-30 10:02:57奥运会纪念徽章:花样游泳
日期:2008-09-26 13:02:43奥运会纪念徽章:排球
日期:2008-12-03 11:23:272010新春纪念徽章
日期:2010-01-04 08:33:082010年世界杯参赛球队:澳大利亚
日期:2010-02-26 11:08:44
13#
发表于 2011-11-1 14:32 | 只看该作者
14:34:51 SQL> set autot traceonly
14:35:11 SQL> select * from t where name is not null;


Execution Plan
----------------------------------------------------------
Plan hash value: 3502950021

----------------------------------------------------------------------------------------
| Id  | Operation                   | Name     | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |          |     1 |     5 |     2   (0)| 00:00:01 |
|   1 |  TABLE ACCESS BY INDEX ROWID| T        |     1 |     5 |     2   (0)| 00:00:01 |
|*  2 |   INDEX FULL SCAN           | I_T_NAME |     1 |       |     1   (0)| 00:00:01 |
----------------------------------------------------------------------------------------

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

   2 - filter("NAME" IS NOT NULL)


Statistics
----------------------------------------------------------
          0  recursive calls
          0  db block gets
          2  consistent gets
          0  physical reads
          0  redo size
        595  bytes sent via SQL*Net to client
        519  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          1  rows processed

使用道具 举报

回复
论坛徽章:
194
红宝石
日期:2014-05-09 08:24:37萤石
日期:2014-01-03 10:25:39奥运会纪念徽章:羽毛球
日期:2008-07-01 10:46:06奥运会纪念徽章:马术
日期:2008-07-07 17:43:24奥运会纪念徽章:射箭
日期:2008-07-25 18:07:39奥运会纪念徽章:皮划艇激流回旋
日期:2008-07-30 10:02:57奥运会纪念徽章:花样游泳
日期:2008-09-26 13:02:43奥运会纪念徽章:排球
日期:2008-12-03 11:23:272010新春纪念徽章
日期:2010-01-04 08:33:082010年世界杯参赛球队:澳大利亚
日期:2010-02-26 11:08:44
14#
发表于 2011-11-1 14:35 | 只看该作者
SQL> set autot off
SQL> select * from t where name is not null;

SQL> select * from table(dbms_xplan.display_cursor(NULL,NULL,'ALLSTATS LAST'));

PLAN_TABLE_OUTPUT
-----------------------------------------------------------------------------------------------------------
SQL_ID  964sufn52x6ua, child number 0
-------------------------------------
select * from t where name is not null

Plan hash value: 3502950021

---------------------------------------------------------
| Id  | Operation                   | Name     | E-Rows |
---------------------------------------------------------
|   0 | SELECT STATEMENT            |          |        |
|   1 |  TABLE ACCESS BY INDEX ROWID| T        |      1 |
|*  2 |   INDEX FULL SCAN           | I_T_NAME |  10000 |
---------------------------------------------------------

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

   2 - filter("NAME" IS NOT NULL)

Note
-----
   - dynamic sampling used for this statement (level=2)
   - Warning: basic plan statistics not available. These are only collected when:
       * hint 'gather_plan_statistics' is used for the statement or
       * parameter 'statistics_level' is set to 'ALL', at session or system level


26 rows selected

走索引全扫描。

使用道具 举报

回复
论坛徽章:
194
红宝石
日期:2014-05-09 08:24:37萤石
日期:2014-01-03 10:25:39奥运会纪念徽章:羽毛球
日期:2008-07-01 10:46:06奥运会纪念徽章:马术
日期:2008-07-07 17:43:24奥运会纪念徽章:射箭
日期:2008-07-25 18:07:39奥运会纪念徽章:皮划艇激流回旋
日期:2008-07-30 10:02:57奥运会纪念徽章:花样游泳
日期:2008-09-26 13:02:43奥运会纪念徽章:排球
日期:2008-12-03 11:23:272010新春纪念徽章
日期:2010-01-04 08:33:082010年世界杯参赛球队:澳大利亚
日期:2010-02-26 11:08:44
15#
发表于 2011-11-1 14:36 | 只看该作者
只要name大部分是NULL,name is not null可以使用索引的。

使用道具 举报

回复
论坛徽章:
194
红宝石
日期:2014-05-09 08:24:37萤石
日期:2014-01-03 10:25:39奥运会纪念徽章:羽毛球
日期:2008-07-01 10:46:06奥运会纪念徽章:马术
日期:2008-07-07 17:43:24奥运会纪念徽章:射箭
日期:2008-07-25 18:07:39奥运会纪念徽章:皮划艇激流回旋
日期:2008-07-30 10:02:57奥运会纪念徽章:花样游泳
日期:2008-09-26 13:02:43奥运会纪念徽章:排球
日期:2008-12-03 11:23:272010新春纪念徽章
日期:2010-01-04 08:33:082010年世界杯参赛球队:澳大利亚
日期:2010-02-26 11:08:44
16#
发表于 2011-11-1 14:38 | 只看该作者
SQL> select * from t where name <>'TEST';

> @dpc

PLAN_TABLE_OUTPUT
-----------------------------------------------------------------
SQL_ID  4jykzkbfysqv4, child number 0
-------------------------------------
select * from t where name <>'TEST'

Plan hash value: 1601196873

-------------------------------------------
| Id  | Operation         | Name | E-Rows |
-------------------------------------------
|   0 | SELECT STATEMENT  |      |        |
|*  1 |  TABLE ACCESS FULL| T    |      1 |
-------------------------------------------

Outline Data
-------------

  /*+
      BEGIN_OUTLINE_DATA
      IGNORE_OPTIM_EMBEDDED_HINTS
      OPTIMIZER_FEATURES_ENABLE('11.2.0.1')
      DB_VERSION('11.2.0.1')
      ALL_ROWS
      OUTLINE_LEAF(@"SEL$1")
      FULL(@"SEL$1" "T"@"SEL$1")
      END_OUTLINE_DATA
  */

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

   1 - filter("NAME"<>'TEST')

Note
-----
   - Warning: basic plan statistics not available. These are only collected when:
       * hint 'gather_plan_statistics' is used for the statement or
       * parameter 'statistics_level' is set to 'ALL', at session or system level

38 rows selected.

这个不行。
看看提示是否可以。

使用道具 举报

回复
论坛徽章:
41
ITPUB9周年纪念徽章
日期:2010-10-08 09:32:26紫蛋头
日期:2012-11-22 10:14:302013年新春福章
日期:2013-02-25 14:51:24鲜花蛋
日期:2013-07-09 19:31:16本田
日期:2013-11-16 13:09:52马上有车
日期: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
17#
 楼主| 发表于 2011-11-1 14:39 | 只看该作者
lfree 发表于 2011-11-1 14:36
只要name大部分是NULL,name is not null可以使用索引的。

斑竹真好,谢谢啦,我记得上次我测试的情况如下:大部分数据都是not null,但是只有少数数据时null,条件中是is null.这种情况好像不走索引呢

使用道具 举报

回复
论坛徽章:
194
红宝石
日期:2014-05-09 08:24:37萤石
日期:2014-01-03 10:25:39奥运会纪念徽章:羽毛球
日期:2008-07-01 10:46:06奥运会纪念徽章:马术
日期:2008-07-07 17:43:24奥运会纪念徽章:射箭
日期:2008-07-25 18:07:39奥运会纪念徽章:皮划艇激流回旋
日期:2008-07-30 10:02:57奥运会纪念徽章:花样游泳
日期:2008-09-26 13:02:43奥运会纪念徽章:排球
日期:2008-12-03 11:23:272010新春纪念徽章
日期:2010-01-04 08:33:082010年世界杯参赛球队:澳大利亚
日期:2010-02-26 11:08:44
18#
发表于 2011-11-1 14:40 | 只看该作者
14:40:31 SQL> select /*+ index(t,i_t_name) */* from t where name <>'TEST';

        ID NAME
---------- ----
         1 test

14:42:52 SQL> @dpc

PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
SQL_ID  5pggmjyx22yxc, child number 0
-------------------------------------
select /*+ index(t,i_t_name) */* from t where name <>'TEST'

Plan hash value: 3502950021

---------------------------------------------------------
| Id  | Operation                   | Name     | E-Rows |
---------------------------------------------------------
|   0 | SELECT STATEMENT            |          |        |
|   1 |  TABLE ACCESS BY INDEX ROWID| T        |      1 |
|*  2 |   INDEX FULL SCAN           | I_T_NAME |      1 |
---------------------------------------------------------

Outline Data
-------------

  /*+
      BEGIN_OUTLINE_DATA
      IGNORE_OPTIM_EMBEDDED_HINTS
      OPTIMIZER_FEATURES_ENABLE('11.2.0.1')
      DB_VERSION('11.2.0.1')
      ALL_ROWS
      OUTLINE_LEAF(@"SEL$1")
      INDEX(@"SEL$1" "T"@"SEL$1" ("T"."NAME"))
      END_OUTLINE_DATA
  */

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

   2 - filter("NAME"<>'TEST')

Note
-----
   - Warning: basic plan statistics not available. These are only collected when:
       * hint 'gather_plan_statistics' is used for the statement or
       * parameter 'statistics_level' is set to 'ALL', at session or system level


39 rows selected.

14:42:54 SQL>

使用道具 举报

回复
论坛徽章:
194
红宝石
日期:2014-05-09 08:24:37萤石
日期:2014-01-03 10:25:39奥运会纪念徽章:羽毛球
日期:2008-07-01 10:46:06奥运会纪念徽章:马术
日期:2008-07-07 17:43:24奥运会纪念徽章:射箭
日期:2008-07-25 18:07:39奥运会纪念徽章:皮划艇激流回旋
日期:2008-07-30 10:02:57奥运会纪念徽章:花样游泳
日期:2008-09-26 13:02:43奥运会纪念徽章:排球
日期:2008-12-03 11:23:272010新春纪念徽章
日期:2010-01-04 08:33:082010年世界杯参赛球队:澳大利亚
日期:2010-02-26 11:08:44
19#
发表于 2011-11-1 14:42 | 只看该作者
使用提示也是可以发现是可以的。

使用道具 举报

回复
论坛徽章:
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
20#
发表于 2011-11-1 14:45 | 只看该作者
改索引改SQL是最好的方法

使用道具 举报

回复

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

本版积分规则 发表回复

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