[20140512]关于降序索引.txt

[20140512]关于降序索引.txt

https://jonathanlewis.wordpress.com/2014/05/07/quiz-night-23/

提到建立降序索引,会出现建立唯一索引出现促错误的问题,自己做一个测试了解一些细节:

1.测试环境:

SCOTT@test> @ver

BANNER
--------------------------------------------------------------------------------
Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - 64bit Production

create table t (id number,name varchar2(10));
insert into t values (1,'aaaaaa');
insert into t values (2,'bbbbbb');
insert into t values (null,null);
insert into t values (null,null);
commit ;

2.可以发现建立唯一索引,但是如果使用降序索引就不行。

SCOTT@test> create unique index i_t_id on t(id);
Index created.

SCOTT@test> create unique index i_t_id on t(id desc);
create unique index i_t_id on t(id desc)
                                *
ERROR at line 1:
ORA-01452: cannot CREATE UNIQUE INDEX; duplicate keys found

--可以发现建立降序索引失败。

3.参见链接:https://jonathanlewis.wordpress.com/2014/05/07/quiz-night-23/
Answer

Well it didn't take long for an answer and several bits of related infomration to show up – as Martin pointed out, all
I have to do is insert NULL into the table twice.

To create an entry in a descending index, Oracle takes the 1's-complement of each column and appends an 0xFF byte to
each column – except in the case of a null column where the null is replaced with a 0x00. (And, as Sayan points out,
funny things happen if you have a varchar2() column which has already reached the 4,000 byte limit)

The point of the 1's-complement is that if you walk through the stored values in ascending order you're walking through
the original values in descending – provided you have the 0xFF on the end of each non-null entry.

4.看看降序索引是如何保存的.
SCOTT@test> create  index i_t_id on t(id desc);
Index created.

SCOTT@test> create  index i_t_name on t(name desc);
Index created.

SCOTT@test> select segment_name,header_file,header_block from dba_segments where owner=user and segment_name in ('I_T_ID','I_T_NAME');
SEGMENT_NAME         HEADER_FILE HEADER_BLOCK
-------------------- ----------- ------------
I_T_NAME                       4         1426
I_T_ID                         4          634

--记录很少,仅仅只有一个索引根节点。

SCOTT@test> alter system dump datafile 4 block 635;
System altered.

SCOTT@test> alter system dump datafile 4 block 1427;
System altered.

--看看里面保存的信息:
Block header dump:  0x0100027b
Object id on Block? Y
seg/obj: 0x45d9b  csc: 0x00.c2f0184a  itc: 2  flg: E  typ: 2 - INDEX
     brn: 0  bdba: 0x1000278 ver: 0x01 opc: 0
     inc: 0  exflg: 0

Itl           Xid                  Uba         Flag  Lck        Scn/Fsc
0x01   0x0000.000.00000000  0x00000000.0000.00  ----    0  fsc 0x0000.00000000
0x02   0xffff.000.00000000  0x00000000.0000.00  C---    0  scn 0x0000.c2f0184a
Leaf block dump
===============
header address 182927221348=0x2a974fe264
kdxcolev 0
KDXCOLEV Flags = - - -
kdxcolok 0
kdxcoopc 0x80: opcode=0: iot flags=--- is converted=Y
kdxconco 2
kdxcosdc 0
kdxconro 4
kdxcofbo 44=0x2c
kdxcofeo 7984=0x1f30
kdxcoavs 7940
kdxlespl 0
kdxlende 0
kdxlenxt 0=0x0
kdxleprv 0=0x0
kdxledsz 0
kdxlebksz 8032
row#0[8021] flag: ------, lock: 0, len=11
col 0; len 1; (1):  00
col 1; len 6; (6):  01 00 02 73 00 02
row#1[8010] flag: ------, lock: 0, len=11
col 0; len 1; (1):  00
col 1; len 6; (6):  01 00 02 73 00 03
row#2[7997] flag: ------, lock: 0, len=13
col 0; len 3; (3):  3e fc ff
col 1; len 6; (6):  01 00 02 73 00 01
row#3[7984] flag: ------, lock: 0, len=13
col 0; len 3; (3):  3e fd ff
col 1; len 6; (6):  01 00 02 73 00 00
----- end of leaf block dump -----
End dump data blocks tsn: 4 file#: 4 minblk 635 maxblk 635

Block header dump:  0x01000593
Object id on Block? Y
seg/obj: 0x45d9c  csc: 0x00.c2f0189c  itc: 2  flg: E  typ: 2 - INDEX
     brn: 0  bdba: 0x1000590 ver: 0x01 opc: 0
     inc: 0  exflg: 0

Itl           Xid                  Uba         Flag  Lck        Scn/Fsc
0x01   0x0000.000.00000000  0x00000000.0000.00  ----    0  fsc 0x0000.00000000
0x02   0xffff.000.00000000  0x00000000.0000.00  C---    0  scn 0x0000.c2f0189c
Leaf block dump
===============
header address 182927221348=0x2a974fe264
kdxcolev 0
KDXCOLEV Flags = - - -
kdxcolok 0
kdxcoopc 0x80: opcode=0: iot flags=--- is converted=Y
kdxconco 2
kdxcosdc 0
kdxconro 4
kdxcofbo 44=0x2c
kdxcofeo 7976=0x1f28
kdxcoavs 7932
kdxlespl 0
kdxlende 0
kdxlenxt 0=0x0
kdxleprv 0=0x0
kdxledsz 0
kdxlebksz 8032
row#0[8021] flag: ------, lock: 0, len=11
col 0; len 1; (1):  00
col 1; len 6; (6):  01 00 02 73 00 02
row#1[8010] flag: ------, lock: 0, len=11
col 0; len 1; (1):  00
col 1; len 6; (6):  01 00 02 73 00 03
row#2[7993] flag: ------, lock: 0, len=17
col 0; len 7; (7):  9d 9d 9d 9d 9d 9d ff
col 1; len 6; (6):  01 00 02 73 00 01
row#3[7976] flag: ------, lock: 0, len=17
col 0; len 7; (7):  9e 9e 9e 9e 9e 9e ff
col 1; len 6; (6):  01 00 02 73 00 00
----- end of leaf block dump -----
End dump data blocks tsn: 4 file#: 4 minblk 1427 maxblk 1427

---可以发现NULL无论number还是varchar2,都是00,在降序索引里面。

SCOTT@test> select dump('aaaaaa',16),dump('bbbbbb',16) from dual ;
DUMP('AAAAAA',16)               DUMP('BBBBBB',16)
------------------------------- -------------------------------
Typ=96 Len=6: 61,61,61,61,61,61 Typ=96 Len=6: 62,62,62,62,62,62

SCOTT@test> @16to10 61
16 to 10 DEC
------------
          97

SCOTT@test> @16to10 9e
16 to 10 DEC
------------
         158

SCOTT@test> select 97+158 from dual ;
    97+158
----------
       255

--可以发现相当于使用0xff与name异或,然后在后面加0xff.看看数字:
row#3[7984] flag: ------, lock: 0, len=13
col 0; len 3; (3):  3e fd ff
col 1; len 6; (6):  01 00 02 73 00 00

SCOTT@test> select dump(1,16),dump(1,10),dump(2,16),dump(2,10) from dual ;
DUMP(1,16)        DUMP(1,10)         DUMP(2,16)        DUMP(2,10)
----------------- ------------------ ----------------- ------------------
Typ=2 Len=2: c1,2 Typ=2 Len=2: 193,2 Typ=2 Len=2: c1,3 Typ=2 Len=2: 193,3

SCOTT@test> @16to10 3e
16 to 10 DEC
------------
          62

SCOTT@test> @16to10 fd
16 to 10 DEC
------------
         253

-- 62+193=255
-- 2+253=255

-- 可以发现数字性也是一样,使用0xff与id异或,然后在后面加0xff.

5.虽然降序索引是这样建立,但是如果这样查询依旧不会使用。
SCOTT@test> execute dbms_stats.gather_table_stats(user,'t',cascade=>true);
PL/SQL procedure successfully completed.

SCOTT@test> select /*+ index(t,i_t_id) */ count(*) from t ;
  COUNT(*)
----------
         4

SCOTT@test> @dpc '' ''
PLAN_TABLE_OUTPUT
-----------------------------------------------------------
SQL_ID  92v6cqgrkpkw2, child number 0
-------------------------------------
select /*+ index(t,i_t_id) */ count(*) from t

Plan hash value: 2966233522

---------------------------------------------------------
| Id  | Operation          | Name | E-Rows | Cost (%CPU)|
---------------------------------------------------------
|   0 | SELECT STATEMENT   |      |        |     3 (100)|
|   1 |  SORT AGGREGATE    |      |      1 |            |
|   2 |   TABLE ACCESS FULL| T    |      4 |     3   (0)|
---------------------------------------------------------

--建立函数索引看看。

SCOTT@test> create index if_t_id on t(id,0);
Index created.

SCOTT@test> select /*+ index(t,if_t_id) */ count(*) from t ;
  COUNT(*)
----------
         4

SCOTT@test> @dpc '' ''
PLAN_TABLE_OUTPUT
-------------------------------------
SQL_ID  2tawnyjhj1ufb, child number 0
-------------------------------------
select /*+ index(t,if_t_id) */ count(*) from t
Plan hash value: 428201273
----------------------------------------------------------
| Id  | Operation        | Name    | E-Rows | Cost (%CPU)|
----------------------------------------------------------
|   0 | SELECT STATEMENT |         |        |     1 (100)|
|   1 |  SORT AGGREGATE  |         |      1 |            |
|   2 |   INDEX FULL SCAN| IF_T_ID |      4 |     1   (0)|
----------------------------------------------------------

时间: 2024-09-25 03:23:11

[20140512]关于降序索引.txt的相关文章

关于Oracle降序索引的定意及回溯

oracle|索引 降序索引本质上是FBI,其具体定义可以通过 user_ind_expressions 或dba_ind_expressions 查询.那么同样的,降序索引只有在CBO下才能被使用. Connected to Oracle9i Enterprise Edition Release 9.2.0.4.0 Connected as eygle SQL> create table t as select * from dba_users; Table created SQL> cre

mysql降序索引和减轻索引扫描

Descending indexing and loose index scan 降序索引和减轻索引扫描 Comments to my previous posts, especially this one by Gokhan inspired me to write a bit about descending indexes and about loose index scan, or what Gokhan calls "better range" support. None o

在SQL2k降序索引上使用中bug

解决SQL2k降序索引上使用对比条件更新或删除的bug我在SQL server 2000 enterprise 和 personal 都试过了, 每次都这样.:(详细情况看我的回贴:SQl server 7.0 中的确没有问题, sql 2000 中(enterprise 和 personal版本都可以),表要有聚簇索引,并且索引的顺序是降序, 例如 按下列DDL sql 建立的表 CREATE TABLE [AType] ( [AID] [int] NOT NULL , [name] [var

ORA FAQ 性能调整系列之——当索引第一列由序列产生,一个逆序索引有什么用?

索引|性能 ORA FAQ 性能调整系列之--The Oracle (tm) Users' Co-Operative FAQWhy would a reverse index be useful when the leading column of the index is generated from a sequence ?当索引第一列由序列产生,一个逆序索引有什么用?--------------------------------------------------------------

PHP中数组元素升序、降序及重新排序的函数

在PHP数组学习摘录部分了解到最基本的PHP数组的建立和数组元素的显示.需要深入学习下PHP数组的相关操作.首先接触的就是数组元素的升序.降序的排序问题. 1,快速创建数组的函数range() 比如range()函数可以快速创建从1到9的数字数组: <?php $numbers=range(1,9);echo $numbers[1];?> 当然,使用range(9,1)则创建了9到1的数字数组.同时,range()还可以创建从a到z 的字符数组: <?php $numbers=range

sql server 2008-如何修改数据库默认排序为降序

问题描述 如何修改数据库默认排序为降序 请教一个问题 以前做的一个东西 查询数据没用order by : 查询出来的数据是按主键 升序排的 现在想改成 按另外一个字段降序排 由于丢失源码 能在数据库里修改吗 尝试新建 视图 索引 均无效 SQLSERVER 2008 解决方案 在管理器中选中数据库,右键-->属性-->选项,右边第一个就是排序规则 解决方案二: http://m.blog.csdn.net/blog/lichxi1002/19611227 解决方案三: 楼上的兄弟 你说的这个我

php arsort 数组降序排序详细介绍_php实例

arsort 对数组进行降序排序并保持索引关系. 基本语法 bool arsort ( array &$array [, int $sort_flags = SORT_REGULAR ] ) 本函数对数组进行降序排序,数组的索引保持和单元的关联. arsort函数主要用于对那些单元顺序很重要的结合数组进行排序. 参数介绍: 参数 描述 array 必需.输入的数组. sort_flags 可选.规定如何排列数组的元素/项目.可能的值: 0 = SORT_REGULAR - 默认.把每一项按常规顺

解析PHP中数组元素升序、降序以及重新排序的函数_php技巧

1,快速创建数组的函数range()比如range()函数可以快速创建从1到9的数字数组: 复制代码 代码如下: <?php $numbers=range(1,9);echo $numbers[1];?> 当然,使用range(9,1)则创建了9到1的数字数组.同时,range()还可以创建从a到z 的字符数组: 复制代码 代码如下: <?php $numbers=range(a,z);foreach ($numbers as $mychrs)    echo $mychrs."

DataGrid连接Access的快速分页法(3)——SQL语句的选用(降序)

access|datagrid|分页|语句 DataGrid连接Access的快速分页法(3)--SQL语句的选用(降序)三.降序(1)@PageIndex <= @FirstIndexSELECT TOP @PageSize @QueryFields FROM @TableName WHERE @ConditionORDER BY @PrimaryKey DESC (2)@FirstIndex < @PageIndex <= @MiddleIndex SELECT TOP @PageS