[20131013]索引部分数据.txt

[20131013]索引部分数据.txt

在实际的生产系统中,比如一个标识状态的字段,'0'的行很少,'1'以及其他值的行很多,一个通过特殊的函数索引,
利用oracle索引不保存NULL的特性(注意如果索引2个字段,2个必须为NULL,索引才不会保存),索引仅仅为'0',
减少索引的大小,实际上网上有许多的例子,正好别人问到,顺手写一个小例子:

1.建立测试例子:

SCOTT@test01p> @ver
BANNER                                                                               CON_ID
-------------------------------------------------------------------------------- ----------
Oracle Database 12c Enterprise Edition Release 12.1.0.1.0 - 64bit Production              0

create table t as select rownum id,lpad('x',80,'x') pad, '1' flag from dual connect by level
insert into t values (9998,lpad('y',80,'y'),'0');
insert into t values (9999,lpad('y',80,'y'),'0');
insert into t values (1000,lpad('y',80,'y'),'0');
commit ;

2.建立函数索引:
create index if_t_flag on t (decode(flag,'0',flag));

validate index if_t_flag;

cat i.sql

set linesize 200;
set linesize 200;
column name format a10
/* select height, blocks, lf_blks, lf_rows_len, lf_blk_len, br_blks, br_rows, br_rows_len, br_blk_len, btree_space, used_space, pct_used from index_stats; */
select HEIGHT, BLOCKS, NAME, LF_ROWS, LF_BLKS, LF_ROWS_LEN, LF_BLK_LEN, BR_ROWS, BR_BLKS, BR_ROWS_LEN, BR_BLK_LEN,
DEL_LF_ROWS, DEL_LF_ROWS_LEN, DISTINCT_KEYS from index_stats;

select MOST_REPEATED_KEY, BTREE_SPACE, USED_SPACE, PCT_USED, ROWS_PER_KEY, BLKS_GETS_PER_ACCESS, PRE_ROWS, PRE_ROWS_LEN,
OPT_CMPR_COUNT, OPT_CMPR_PCTSAVE from index_stats;

--查询index_stats内容太多,分2次查询

SCOTT@test01p> @i
    HEIGHT     BLOCKS NAME          LF_ROWS    LF_BLKS LF_ROWS_LEN LF_BLK_LEN    BR_ROWS    BR_BLKS BR_ROWS_LEN BR_BLK_LEN DEL_LF_ROWS DEL_LF_ROWS_LEN DISTINCT_KEYS
---------- ---------- ---------- ---------- ---------- ----------- ---------- ---------- ---------- ----------- ---------- ----------- --------------- -------------
         1          8 IF_T_FLAG           3          1          39       8000          0          0           0          0           0               0             1
MOST_REPEATED_KEY BTREE_SPACE USED_SPACE   PCT_USED ROWS_PER_KEY BLKS_GETS_PER_ACCESS   PRE_ROWS PRE_ROWS_LEN OPT_CMPR_COUNT OPT_CMPR_PCTSAVE
----------------- ----------- ---------- ---------- ------------ -------------------- ---------- ------------ -------------- ----------------
                3        8000         39          1            3                    3          0            0              0                0

--可以发现LF_ROWS=3,也就是仅仅索引3个值。

3.测试:
SCOTT@test01p> exec dbms_stats.gather_table_stats(ownname=>user, tabname=>'T', method_opt=>'FOR ALL COLUMNS SIZE 1');
PL/SQL procedure successfully completed.

SCOTT@test01p> select * from t where flag='0';
        ID PAD                                                                              F
---------- -------------------------------------------------------------------------------- -
      9998 yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy 0
      9999 yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy 0
      1000 yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy 0
SCOTT@test01p> @dpc '' ''
PLAN_TABLE_OUTPUT
-------------------------------------
SQL_ID  2puf1jju69u3q, child number 0
-------------------------------------
select * from t where flag='0'
Plan hash value: 1601196873
--------------------------------------------------------
| Id  | Operation         | Name | E-Rows | Cost (%CPU)|
--------------------------------------------------------
|   0 | SELECT STATEMENT  |      |        |    53 (100)|
|*  1 |  TABLE ACCESS FULL| T    |   5000 |    53   (0)|
--------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   1 - filter("FLAG"='0')

--可以发现并没有使用我们建立的函数索引。当然这些写sql没有问题。

SCOTT@test01p> select * from t where decode(flag,'0',flag)='0';
        ID PAD                                                                              F
---------- -------------------------------------------------------------------------------- -
      9998 yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy 0
      9999 yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy 0
      1000 yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy 0
SCOTT@test01p> @dpc '' ''
PLAN_TABLE_OUTPUT
-------------------------------------
SQL_ID  fh0kpz3trj8m7, child number 0
-------------------------------------
select * from t where decode(flag,'0',flag)='0'
Plan hash value: 3731093196
-------------------------------------------------------------------------------
| Id  | Operation                           | Name      | E-Rows | Cost (%CPU)|
-------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                    |           |        |     2 (100)|
|   1 |  TABLE ACCESS BY INDEX ROWID BATCHED| T         |      3 |     2   (0)|
|*  2 |   INDEX RANGE SCAN                  | IF_T_FLAG |      3 |     1   (0)|
-------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   2 - access("T"."SYS_NC00004$"='0')

4.看看加入hint如何?

SCOTT@test01p> select /*+ index(t if_t_flag) */ * from t where flag='0';
        ID PAD                                                                              F
---------- -------------------------------------------------------------------------------- -
      9998 yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy 0
      9999 yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy 0
      1000 yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy 0
SCOTT@test01p> @dpc '' ''
PLAN_TABLE_OUTPUT
-------------------------------------
SQL_ID  gzdxqc9dgz0vv, child number 0
-------------------------------------
select /*+ index(t if_t_flag) */ * from t where flag='0'
Plan hash value: 1601196873
--------------------------------------------------------
| Id  | Operation         | Name | E-Rows | Cost (%CPU)|
--------------------------------------------------------
|   0 | SELECT STATEMENT  |      |        |    53 (100)|
|*  1 |  TABLE ACCESS FULL| T    |   5000 |    53   (0)|
--------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   1 - filter("FLAG"='0')

5.在谓词是flag='0',不会使用函数索引。在测试使用case函数。
create index if1_t_flag  on t( case flag when '0' then flag end);

SCOTT@test01p> validate index if1_t_flag ;

Index analyzed.

SCOTT@test01p> @i
    HEIGHT     BLOCKS NAME          LF_ROWS    LF_BLKS LF_ROWS_LEN LF_BLK_LEN    BR_ROWS    BR_BLKS BR_ROWS_LEN BR_BLK_LEN DEL_LF_ROWS DEL_LF_ROWS_LEN DISTINCT_KEYS
---------- ---------- ---------- ---------- ---------- ----------- ---------- ---------- ---------- ----------- ---------- ----------- --------------- -------------
         1          8 IF1_T_FLAG          3          1          39       8000          0          0           0          0           0               0             1

MOST_REPEATED_KEY BTREE_SPACE USED_SPACE   PCT_USED ROWS_PER_KEY BLKS_GETS_PER_ACCESS   PRE_ROWS PRE_ROWS_LEN OPT_CMPR_COUNT OPT_CMPR_PCTSAVE
----------------- ----------- ---------- ---------- ------------ -------------------- ---------- ------------ -------------- ----------------
                3        8000         39          1            3                    3          0            0              0                0

SCOTT@test01p> exec dbms_stats.gather_table_stats(ownname=>user, tabname=>'T', method_opt=>'FOR ALL COLUMNS SIZE 1');
PL/SQL procedure successfully completed.

SCOTT@test01p> select * from t where flag='0';
        ID PAD                                                                              F
---------- -------------------------------------------------------------------------------- -
      9998 yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy 0
      9999 yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy 0
      1000 yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy 0
SCOTT@test01p> @dpc '' ''
PLAN_TABLE_OUTPUT
-------------------------------------
SQL_ID  2puf1jju69u3q, child number 0
-------------------------------------
select * from t where flag='0'
Plan hash value: 1601196873
--------------------------------------------------------
| Id  | Operation         | Name | E-Rows | Cost (%CPU)|
--------------------------------------------------------
|   0 | SELECT STATEMENT  |      |        |    53 (100)|
|*  1 |  TABLE ACCESS FULL| T    |   5000 |    53   (0)|
--------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   1 - filter("FLAG"='0')

--依旧没使用函数索引。

6.加提示看看:

SCOTT@test01p> select /*+ index(t if1_t_flag) */ count(*) from t where flag='0';
  COUNT(*)
----------
         3
SCOTT@test01p> @dpc '' ''
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
SQL_ID  6hu6t6w2f8gdg, child number 0
-------------------------------------
select /*+ index(t if1_t_flag) */ count(*) from t where flag='0'
Plan hash value: 2966233522
---------------------------------------------------------
| Id  | Operation          | Name | E-Rows | Cost (%CPU)|
---------------------------------------------------------
|   0 | SELECT STATEMENT   |      |        |    53 (100)|
|   1 |  SORT AGGREGATE    |      |      1 |            |
|*  2 |   TABLE ACCESS FULL| T    |   5000 |    53   (0)|
---------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   2 - filter("FLAG"='0')

--依旧不行。

7.加入约束后:
SCOTT@test01p> alter table t modify flag not null;
Table altered.

--结果也一样,不再另行测试。

也就是讲要使用这种方式,需要开发与DBA的配合来完成。

8.在11G后,可以建立分区索引解决这个问题:
create index IF2_T_FLAG on T(flag) global partition by range (flag) (
  partition p_flag0 values less than ('1'),
  partition p_OTHER values less than (MAXVALUE)
) unusable;

--注意我使用unusable参数,没有空间的使用。

SCOTT@test01p> select  table_name ,index_name,segment_created from user_indexes where table_name='T';
TABLE_NAME INDEX_NAME           SEG
---------- -------------------- ---
T          IF2_T_FLAG           N/A
T          IF1_T_FLAG           YES
T          IF_T_FLAG            YES
SCOTT@test01p> alter index if2_t_flag rebuild partition p_flag0;
Index altered.
SCOTT@test01p> select  segment_name ,PARTITION_NAME,segment_type ,bytes from user_segments where segment_name='IF2_T_FLAG' ;
SEGMENT_NAME         PARTITION_NAME       SEGMENT_TYPE            BYTES
-------------------- -------------------- ------------------ ----------
IF2_T_FLAG           P_FLAG0              INDEX PARTITION         65536
SCOTT@test01p> select  * from t where  flag='0';
        ID PAD                                                                              F
---------- -------------------------------------------------------------------------------- -
      9998 yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy 0
      9999 yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy 0
      1000 yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy 0
SCOTT@test01p> @dpc '' ''
PLAN_TABLE_OUTPUT
-------------------------------------
SQL_ID  gjpvzujvambrj, child number 0
-------------------------------------
select  * from t where  flag='0'
Plan hash value: 2463861812
---------------------------------------------------------------------------------
| Id  | Operation                            | Name       | E-Rows | Cost (%CPU)|
---------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                     |            |        |     1 (100)|
|   1 |  PARTITION RANGE SINGLE              |            |      3 |     1   (0)|
|   2 |   TABLE ACCESS BY INDEX ROWID BATCHED| T          |      3 |     1   (0)|
|*  3 |    INDEX RANGE SCAN                  | IF2_T_FLAG |      3 |     1   (0)|
---------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   3 - access("FLAG"='0')

9.12c下方法更多,看http://richardfoote.wordpress.com的blog有许多介绍。
这里不再重复了。

时间: 2024-08-25 18:42:04

[20131013]索引部分数据.txt的相关文章

[20171202]关于函数索引的状态.txt

[20171202]关于函数索引的状态.txt --//我曾经在一篇贴子提到索引可以disable吗?链接: --//http://blog.itpub.net/267265/viewspace-2123537/ --//实际上仅仅函数索引能disable,为什么呢?实际上自己以前并不搞清楚实际上这个跟oracle使用函数的特殊性有关. --//如果一个表删除某个字段,对应的索引也会删除.如果定义的函数删除了,对应的函数索引呢?通过例子来说明问题: 1.环境: SCOTT@test01p> @

[20150626]建立索引pctfree=0.txt

[20150626]建立索引pctfree=0.txt --昨天看了链接: https://richardfoote.wordpress.com/2015/06/25/quiz-time-why-do-deletes-cause-an-index-to-grow-up-the-hill-backwards/ --自己测试看看来解答问题,不知道是否正确:-) 1.建立测试环境: SCOTT@test> @ver1 PORT_STRING                    VERSION    

[20150926]索引压缩问题.txt

[20150926]索引压缩问题.txt --以前如果索引前缀重复值很多,我会选择索引压缩,这样减少磁盘空间占用,索引范围扫描也可以减少磁盘IO,虽然这样可能消耗一些 --CUP资源,感觉影响不大. --看了链接感觉自己忽略一些问题,可能导致达不到预期效果. --通过例子来说明: 1.建立测试环境: SCOTT@test01p> @ver1 PORT_STRING                    VERSION        BANNER                          

[20121015]探索索引-学习bbed.txt

[20121015]探索索引-学习bbed.txt 参考链接:http://www.adellera.it/blog/2009/05/24/order-keys-inside-index-blocks/ 1.探索索引 SQL> select * from v$version; BANNER -------------------------------------------------------------------------------- Oracle Database 11g Ent

[20130729]位图索引与死锁.txt

[20130729]位图索引与死锁.txt 昨天遇到一例使用位图索引导致死锁的例子,记录一下. 1.建立测试环境:SQL> @verBANNER--------------------------------------------------------------------------------Oracle Database 12c Enterprise Edition Release 12.1.0.1.0 - 64bit Production SQL> create table t(

[20140827]imp exp 使用管道迁移数据.txt

[20140827]imp exp 使用管道迁移数据.txt --最近帮别人升级一套数据库,9i到11g. --那个慢真让人受不了,也许是以前的老机器性能不行.数据量并不大.导出花了时间比较长. --我很久就知道导出可以管道压缩导出文件,实现一边导出一边压缩的功能,现在硬盘空间都很大,很少考虑这种方式. --而且现在很少使用这种方式备份数据. --是否可以使用管道实现一边导出一边导入呢?这样可以节约时间,我做了一个测试: --全部操作都在目的端进行,主要是exp/imp版本问题(烦),操作系统都

用MySQL建立索引时数据表怎样建立?

问题描述 用MySQL建立索引时数据表怎样建立? 长度的字符串位置,大致是这样: 字符串 位置 |ABCD| {1.1,1.11,3.6,...} | |BCDC| {1.2,3.7,...} | |CDCD| {1.3,...} | |.... | {...} | (比如:搜索ABCD,返回{1.1,1.11,3.6}) 我打算将固定长度的字符串作为关键字,位置作为数据. 我知道MySQL里的游标逐条处理数据,但是怎么用原始数据建立数据表?需要什么?希望有人指导一下,万分 解决方案 你这个是全

新人拼凑的码,求解为什么D\\点云数据.txt中没有写入数据!!

问题描述 新人拼凑的码,求解为什么D\点云数据.txt中没有写入数据!! using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Microsoft.Kinect; using System.IO; using System.Windows.Forms; namespace GetPointCloudFromK

c#-用C#进行存储数据txt数据,要求按照以下规则

问题描述 用C#进行存储数据txt数据,要求按照以下规则 对于以下txt数据,要将第一行单独存储,对于2到7单独存储,队友下面的数据L和S之后的数据单独存储,应该怎么用StreamWriter写入数组中,之前的点号单独存储,并能方便以后调用, 3.5,5,5 ID147,312303.586,499860.308 ID148,311970.966,499740.297 ID164,303521.015,497684.195 ID165,303069.052,497407.154 ID180,29