快上网专注成都网站设计 成都网站制作 成都网站建设
成都网站建设公司服务热线:028-86922220

网站建设知识

十年网站开发经验 + 多家企业客户 + 靠谱的建站团队

量身定制 + 运营维护+专业推广+无忧售后,网站问题一站解决

如何进行null与index的分析

这期内容当中小编将会给大家带来有关如何进行null与index的分析,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。

目前累计服务客户上1000+,积累了丰富的产品开发及服务经验。以网站设计水平和技术实力,树立企业形象,为客户提供网站设计、成都做网站、网站策划、网页设计、网络营销、VI设计、网站改版、漏洞修补等服务。成都创新互联公司始终以务实、诚信为根本,不断创新和提高建站品质,通过对领先技术的掌握、对创意设计的研究、对客户形象的视觉传递、对应用系统的结合,为客户提供更好的一站式互联网解决方案,携手广大客户,共同发展进步。

今天在测试过程中遇到一问题, SQL该走Index的,没走. 加index hint也不行. 描述如下:

1. 建立测试表
create table t1
as
select object_id, object_name from dba_objects;



2. 在object_name列上建立b-tree index
create index idx_t1_name on t1(object_name);



3. 如果我是select object_name from t1, 按理说CBO应该会选择走Index scan. 但奇怪的是结果走的full table scan.
SQL> set autotrace trace exp
SQL> select object_name from t1;


Execution Plan
----------------------------------------------------------
Plan hash value: 3617692013


--------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 50934 | 3282K| 57 (2)| 00:00:01 |
| 1 | TABLE ACCESS FULL| T1 | 50934 | 3282K| 57 (2)| 00:00:01 |
--------------------------------------------------------------------------


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


[@more@]
3. 使用index hint想强行走Index, 结果还是full table scan. 我就奇怪了. hint咋个不起做用呢? 郁闷.
SQL> select /*+ index(t1, idx_t1_name) */ object_name from t1;


Execution Plan
----------------------------------------------------------
Plan hash value: 3617692013


--------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 50934 | 3282K| 57 (2)| 00:00:01 |
| 1 | TABLE ACCESS FULL| T1 | 50934 | 3282K| 57 (2)| 00:00:01 |
--------------------------------------------------------------------------


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




4. 偶然看了下表结构
SQL> desc t1
Name Null? Type
----------------------------------------- -------- ----------------------------
OBJECT_ID NUMBER
OBJECT_NAME VARCHAR2(128)




NULL列引起我的注意. OBJECT_NAME可以为null !! 而在oracle中单个列上建b-tree Index, null是不会存进Index的( 复合索引可以, 只要整个Index columns不为null ). 那就是说如果有些行的object_name是null, 那走Index取值不是会丢掉object_name为null的行. 那如果我让object_name not null 呢?


SQL> alter table t1 modify object_name not null;


Table altered.


SQL> desc t1
Name Null? Type
----------------------------------------- -------- ----------------------------
OBJECT_ID NUMBER
OBJECT_NAME NOT NULL VARCHAR2(128)




再试一试
SQL> select object_name from t1;


Execution Plan
----------------------------------------------------------
Plan hash value: 3617692013


--------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 50934 | 3282K| 57 (2)| 00:00:01 |
| 1 | TABLE ACCESS FULL| T1 | 50934 | 3282K| 57 (2)| 00:00:01 |
--------------------------------------------------------------------------


结果还是full table scan : (


试试用hint
SQL> select /*+ index(t1, idx_t1_name) */ object_name from t1;


Execution Plan
---------------------------------------------------------- 
Plan hash value: 1352742509 


--------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 50934 | 3282K| 264 (1)| 00:00:04 |
| 1 | INDEX FULL SCAN | IDX_T1_NAME | 50934 | 3282K| 264 (1)| 00:00:04 |




这回hint 起作用了. 这说明并不是Hint失效, 只是满足走Index的条件一开始没有具备. 看来null是个潜在杀手, 得小心防范. 
现在强走index是ok了. 但, 是什么东西会影响CBO的判断不走Index呢? 想到统计信息可能会是原因之一, 于是查看了一下.


SQL> select index_name, LAST_ANALYZED from user_indexes;
INDEX_NAME LAST_ANALYZED 
------------------------------------------------------------------------------------------ --------------- 
IDX_T1_NAME 01-MAR-18




SQL> select table_name, LAST_ANALYZED from user_tables;


TABLE_NAME LAST_ANALYZED 
------------------------------------------------------------------------------------------ --------------- 
T1




看到刚建的表没有做过统计. 于是 go to analyze table, 结果如下:


SQL> exec dbms_stats.gather_table_stats('TEST','T1');


PL/SQL procedure successfully completed.


SQL> select table_name, LAST_ANALYZED from user_tables;


TABLE_NAME LAST_ANALYZED 
------------------------------------------------------------------------------------------ --------------- 
T1 01-MAR-18




再来看看执行结果有没有变化:
SQL> select object_name from t1;


Execution Plan
---------------------------------------------------------- 
Plan hash value: 222950081




------------------------------------------------------------------------------------ 
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | 
------------------------------------------------------------------------------------ 
| 0 | SELECT STATEMENT | | 49917 | 1218K| 57 (2)| 00:00:01 | 
| 1 | INDEX FAST FULL SCAN| IDX_T1_NAME | 49917 | 1218K| 57 (2)| 00:00:01 | 
------------------------------------------------------------------------------------


这下终于走Index这条路老 : ) 在Index 中, key value是排序存放的. Index Fast full scan 它是按照block的存储顺序来读取数据, 并可以一次I/O多块读取提高效率( 参数 readdb_file_multiblock_read_count), 但返回的值是没有排序的. 而
Index full scan会按照Key value顺序读取值, 返回排了序的结果. 所以, 做个order by会是走Index full scan.


SQL> select object_name from t1 order by object_name;


Execution Plan
---------------------------------------------------------- 
Plan hash value: 1352742509

-------------------------------------------------------------------------------- 
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | 
-------------------------------------------------------------------------------- 
| 0 | SELECT STATEMENT | | 49917 | 1218K| 249 (1)| 00:00:03 | 
| 1 | INDEX FULL SCAN | IDX_T1_NAME | 49917 | 1218K| 249 (1)| 00:00:03 | 
--------------------------------------------------------------------------------

对于定义为NULL的列,创建位图索引可走索引

上述就是小编为大家分享的如何进行null与index的分析了,如果刚好有类似的疑惑,不妨参照上述分析进行理解。如果想知道更多相关知识,欢迎关注创新互联行业资讯频道。


分享题目:如何进行null与index的分析
分享链接:http://6mz.cn/article/jcgede.html

其他资讯