暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Oracle 调整列名不为null的位置

ASKTOM 2020-02-25
360

问题描述

嗨,团队,

我正在尝试创建测试场景,其中使用1列ID创建表名测试。

 Name                                                                                                              Null?    Type
 ----------------------------------------------------------------------------------------------------------------- -------- ----------------------------------------------------------------------------
 ID                                                                                                                         NUMBER


测试表中的值:


SQL> select count(*) ,id from test  group by id;

  COUNT(*)         ID
---------- ----------
         9          1
     99991



我的查询是当试图触发下面的语句:

select count(*) from Test where id is not null ;


我在一个计划中看到,索引全扫描正在发生。我们已经收集了ID的直方图,我们仍然看到索引全扫描

我的问题是,如果我试图选择整个表,如在where子句: 其中id为null,如果这去FTS,我可以理解。

但是,如果我的where子句的where id不为null,则不应进入索引全扫描,尤其是当我有直方图时

select /* 002 */ count(*) from test where id is not  null

Plan hash value: 3822811674

----------------------------------------------------------------------------
| Id  | Operation        | Name    | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------
|   0 | SELECT STATEMENT |         |       |       |     1 (100)|          |
|   1 |  SORT AGGREGATE  |         |     1 |     1 |            |          |
|*  2 |   INDEX FULL SCAN| AMRIT_1 |     9 |     9 |     1   (0)| 00:00:01 |
----------------------------------------------------------------------------

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

   2 - filter("ID" IS NOT NULL)


请您在此处进行指导,并让我们了解更多信息

问候,
克里希纳




专家解答

it should not go in index full scan

你想要数据库做什么?全面扫描表?为什么?为什么有直方图会有什么不同?

要记住的关键是索引通常在物理上小于它所在的表。

因此,完全扫描索引读取的数据少于完全扫描表。

因此,阅读索引应该更快。

在这种情况下,索引比表小得多。因为Oracle数据库从BTrees中排除空条目。所以要读取的数据少了很多!

使用char(1000) 列重新创建示例以使行 “大”。

使用索引和表时,请密切注意缓冲区列:

create table t (
  c1 char(1000)
);

insert into t 
with rws as (
  select level x from dual
  connect by level <= 100000
)
  select case when x < 10 then x end 
  from   rws;

create index i 
  on t ( c1 );
  
alter session set statistics_level = all;
cl scr
select count(*) from t where c1 is not null ;

select * 
from   table(dbms_xplan.display_cursor(null, null, 'ALLSTATS LAST'));

----------------------------------------------------------------------------------------    
| Id  | Operation             | Name | Starts | E-Rows | A-Rows |   A-Time   | Buffers |    
----------------------------------------------------------------------------------------    
|   0 | SELECT STATEMENT      |      |      1 |        |      1 |00:00:00.01 |       6 |    
|   1 |  SORT AGGREGATE       |      |      1 |      1 |      1 |00:00:00.01 |       6 |    
|*  2 |   INDEX FAST FULL SCAN| I    |      1 |      8 |      9 |00:00:00.01 |       6 |    
----------------------------------------------------------------------------------------

select /*+ full ( t ) */count(*) from t where c1 is not null ;

select * 
from   table(dbms_xplan.display_cursor(null, null, 'ALLSTATS LAST'));

-------------------------------------------------------------------------------------    
| Id  | Operation          | Name | Starts | E-Rows | A-Rows |   A-Time   | Buffers |    
-------------------------------------------------------------------------------------    
|   0 | SELECT STATEMENT   |      |      1 |        |      1 |00:00:00.01 |     191 |    
|   1 |  SORT AGGREGATE    |      |      1 |      1 |      1 |00:00:00.01 |     191 |    
|*  2 |   TABLE ACCESS FULL| T    |      1 |      8 |      9 |00:00:00.01 |     191 |    
-------------------------------------------------------------------------------------  


缓冲区 => 逻辑I/O操作

所以

全索引扫描 = 6 I/Os
全表扫描 = 191 I/Os

所以 reading the table is orders of magnitude more work than reading the index!

所以, why do you NOT want to read the index again?
文章转载自ASKTOM,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论