首页 > 其他分享 >[20231105]降序索引的疑问.txt

[20231105]降序索引的疑问.txt

时间:2023-11-10 20:35:22浏览次数:33  
标签:.-- 降序 vl t1 SYS 索引 chr txt 20231105

[20231105]降序索引的疑问.txt

--//我们生产系统有一套系统我以前维护过,出现一个奇葩现象,建立一堆降序索引,实际上完全没有必要,最后我改了许多索引为普通索引.
--//由于可能后续维护或者可能是我遗漏了(当然还有可能索引太大我没有修改),还是有一些索引没改过来.
--//我讲过降序索引的一些问题,比如如果索引列是递增的,降序索引可以讲人为导致索引变大,因为这时的分裂变成50-50分裂.而且降序
--//索引包含NULL值,实际上当查询条件出现is null时,根本不会使用索引.
--//可以最近我遇到1个问题,通过例子说明:

1.环境:
SCOTT@test01p> @ver1
PORT_STRING                    VERSION        BANNER                                                                               CON_ID
------------------------------ -------------- -------------------------------------------------------------------------------- ----------
IBMPC/WIN_NT64-9.1.0           12.2.0.1.0     Oracle Database 12c Enterprise Edition Release 12.2.0.1.0 - 64bit Production              0

SCOTT@test01p> show parameter max_string_size
NAME             TYPE    VALUE
---------------- ------- ----------
max_string_size  string  EXTENDED

2.测试:
SCOTT@test01p> create table t1 ( id number(10),vc varchar2(10), cr_date date,vl varchar2(4000));
Table created.
SCOTT@test01p> @ o2 t1
SCOTT@test01p> @ pr
==============================
O_OWNER                       : SCOTT
O_OBJECT_NAME                 : T1
O_OBJECT_TYPE                 : TABLE
SUBOBJECT_NAME                :
O_STATUS                      : VALID
OID                           : 30357
D_OID                         : 30357
CREATED                       : 2023-11-05 20:38:33
LAST_DDL_TIME                 : 2023-11-05 20:38:33
PL/SQL procedure successfully completed.

SCOTT@test01p> create index if_t1_id on t1(id desc);
Index created.

SCOTT@test01p> create index if_t1_vc on t1(vc desc);
Index created.

SCOTT@test01p> create index if_t1_cr_date on t1(cr_date desc);
Index created.

SCOTT@test01p> create index if_t1_vl on t1(vl desc);
Index created.
--//建立了4个降序索引.

SCOTT@test01p> select OBJ#,COL#,SEGCOL#,SEGCOLLENGTH,name,LENGTH,DEFLENGTH from sys.col$ where obj#='30357';
      OBJ#       COL#    SEGCOL# SEGCOLLENGTH NAME         LENGTH  DEFLENGTH
---------- ---------- ---------- ------------ ------------ ------ ----------
     30357          1          1           22 ID               22
     30357          2          2           10 VC               10
     30357          3          3            7 CR_DATE           7
     30357          4          4         4000 VL             4000
     30357          0          0           34 SYS_NC00005$     34          4
     30357          0          0           16 SYS_NC00006$     16          4
     30357          0          0           12 SYS_NC00007$     12          9
     30357          0          0         6001 SYS_NC00008$   6001          4
8 rows selected.

--//注意看SEGCOLLENGTH列,SYS_NC0000N$的长度都比原来大.大致推断SEGCOLLENGTH*1.5+1.
--//比如: 7*1.5+1 = 11.5  ,取整就是12.
--//实际上很好理解我以前写过降序排序的编码问题.正常情况是编码 与 0xff 异或,最后在结尾加上0xff编码,最后加的主要是排序的需
--//要,这样带来了问题chr(0)的编码就不能是0xff了,这样oracle在一些字符上产生一套不同的编码,并且要考虑排序问题.
--//我曾经画过一个表格:

ASCII码                 编码
---------------------------------------------
0x00                    FEFE
0x0000                  FEFD
0x0001                  FEFC
0x00NN(0xNN>=0x02)      FEFB
0x01                    FEFA
0x0100                  FEF9
0x0101                  FEF8        
0x01NN(0xNN>=0x02)      FEF7
---------------------------------------------
--//比如 0x0003 的编码就是 FEFB FC.

SCOTT@test01p> select SYS_OP_DESCEND(chr(0)||chr(3)),SYS_OP_DESCEND(null) from dual ;
SYS_OP_D SY
-------- --
FEFBFCFF 00

--//这样索引后为了保证键值不会溢出,函数索引raw类型长度必须是原来的1.5倍+结尾的1个字符(0xff).

--//顺便测试is null查询是否会使用索引.
SCOTT@test01p> select * from t1 where id is null;
no rows selected

SCOTT@test01p> @ dpc '' '' ''
PLAN_TABLE_OUTPUT
-------------------------------------
SQL_ID  bnt89b4qftcd0, child number 0
-------------------------------------
select * from t1 where id is null
Plan hash value: 3617692013
---------------------------------------------------------------------------
| Id  | Operation         | Name | E-Rows |E-Bytes| Cost (%CPU)| E-Time   |
---------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      |        |       |     2 (100)|          |
|*  1 |  TABLE ACCESS FULL| T1   |      1 |  2031 |     2   (0)| 00:00:01 |
---------------------------------------------------------------------------
Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------
   1 - SEL$1 / T1@SEL$1
Predicate Information (identified by operation id):
---------------------------------------------------
   1 - filter("ID" IS NULL)
--//你可以发现并不会使用索引.我猜测不是等值的缘故.
--//如果你写成如下,可以使用索引的.

SCOTT@test01p> select * from t1 where SYS_OP_DESCEND(id)=hextoraw('00');
no rows selected

SCOTT@test01p> @ dpc '' '' ''
PLAN_TABLE_OUTPUT
-------------------------------------
SQL_ID  aucnd2w7hcm3w, child number 0
-------------------------------------
select * from t1 where SYS_OP_DESCEND(id)=hextoraw('00')
Plan hash value: 2882164202
-------------------------------------------------------------------------------------------------
| Id  | Operation                           | Name     | E-Rows |E-Bytes| Cost (%CPU)| E-Time   |
-------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                    |          |        |       |     1 (100)|          |
|   1 |  TABLE ACCESS BY INDEX ROWID BATCHED| T1       |      1 |  2031 |     1   (0)| 00:00:01 |
|*  2 |   INDEX RANGE SCAN                  | IF_T1_ID |      1 |       |     1   (0)| 00:00:01 |
-------------------------------------------------------------------------------------------------
Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------
   1 - SEL$1 / T1@SEL$1
   2 - SEL$1 / T1@SEL$1
Predicate Information (identified by operation id):
---------------------------------------------------
   2 - access("T1"."SYS_NC00005$"=HEXTORAW('00'))

3.我不知道是否扩展max_string_size=EXTENDED的原因.
--//如果在18c或者19c呢?

[email protected]:1521/orcl> @ pr
==============================
PORT_STRING                   : x86_64/Linux 2.4.xx
VERSION                       : 18.0.0.0.0
BANNER                        : Oracle Database 18c Enterprise Edition Release 18.0.0.0.0 - Production
BANNER_FULL                   : Oracle Database 18c Enterprise Edition Release 18.0.0.0.0 - Production
Version 18.3.0.0.0
BANNER_LEGACY                 : Oracle Database 18c Enterprise Edition Release 18.0.0.0.0 - Production
CON_ID                        : 0
PL/SQL procedure successfully completed.

create table t1 ( id number(10),vc varchar2(10), cr_date date,vl varchar2(4000));
create index if_t1_id on t1(id desc);
create index if_t1_vc on t1(vc desc);
create index if_t1_cr_date on t1(cr_date desc);
create index if_t1_vl on t1(vl desc);

[email protected]:1521/orcl> @ o2 t1
[email protected]:1521/orcl> @ pr
==============================
O_OWNER                       : TTT
O_OBJECT_NAME                 : T1
O_OBJECT_TYPE                 : TABLE
SEG_PART_NAME                 :
O_STATUS                      : VALID
OID                           : 427915
D_OID                         : 427915
CREATED                       : 2023-11-07 09:56:12
LAST_DDL_TIME                 : 2023-11-07 09:56:12
PL/SQL procedure successfully completed.

[email protected]:1521/orcl> select OBJ#,COL#,SEGCOL#,SEGCOLLENGTH,name,LENGTH,DEFLENGTH from sys.col$ where obj#='427915';
      OBJ#       COL#    SEGCOL# SEGCOLLENGTH NAME         LENGTH  DEFLENGTH
---------- ---------- ---------- ------------ ------------ ------ ----------
    427915          1          1           22 ID               22
    427915          2          2           10 VC               10
    427915          3          3            7 CR_DATE           7
    427915          4          4         4000 VL             4000
    427915          0          0           34 SYS_NC00005$     34          4
    427915          0          0           16 SYS_NC00006$     16          4
    427915          0          0           12 SYS_NC00007$     12          9
    427915          0          0         2000 SYS_NC00008$   2000          4
8 rows selected.
--//除了VL字段的降序索引SEGCOLLENGTH=2000,其它一样.

--//11g呢?前面步骤略.
SCOTT@book> @ver1
PORT_STRING                    VERSION        BANNER
------------------------------ -------------- --------------------------------------------------------------------------------
x86_64/Linux 2.4.xx            11.2.0.4.0     Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production

SCOTT@book> @ o2 t1
SCOTT@book> @ pr
==============================
O_OWNER                       : SCOTT
O_OBJECT_NAME                 : T1
O_OBJECT_TYPE                 : TABLE
SEG_PART_NAME                 :
O_STATUS                      : VALID
OID                           : 90380
D_OID                         : 90380
CREATED                       : 2023-11-07 09:59:37
LAST_DDL_TIME                 : 2023-11-07 09:59:37

PL/SQL procedure successfully completed.

SCOTT@book> select OBJ#,COL#,SEGCOL#,SEGCOLLENGTH,name,LENGTH,DEFLENGTH from sys.col$ where obj#='90380';
      OBJ#       COL#    SEGCOL# SEGCOLLENGTH NAME         LENGTH  DEFLENGTH
---------- ---------- ---------- ------------ ------------ ------ ----------
     90380          1          1           22 ID               22
     90380          2          2           10 VC               10
     90380          3          3            7 CR_DATE           7
     90380          4          4         4000 VL             4000
     90380          0          0           34 SYS_NC00005$     34          4
     90380          0          0           16 SYS_NC00006$     16          4
     90380          0          0           12 SYS_NC00007$     12          9
     90380          0          0         4000 SYS_NC00008$   4000          4
8 rows selected.

--//除了VL字段的降序索引SEGCOLLENGTH=4000.我不知道是否12c我的测试环境配置max_string_size=EXTENDED.
--//这样带来的问题是可能一些数据无法插入.
--//11G的测试:

SCOTT@book> insert into t1(vl) values(lpad('a',3998,'a')||chr(0)||chr(2));
insert into t1(vl) values(lpad('a',3998,'a')||chr(0)||chr(2))
            *
ERROR at line 1:
ORA-01706: user function result value was too large


SCOTT@book> insert into t1(vl) values(lpad('a',3999,'a')||chr(0));
insert into t1(vl) values(lpad('a',3999,'a')||chr(0))
            *
ERROR at line 1:
ORA-01706: user function result value was too large

--//当然18c插入长度更小.
[email protected]:1521/orcl> insert into t1(vl) values(lpad('a',1998,'a')||chr(0));
1 row created.

[email protected]:1521/orcl> insert into t1(vl) values(lpad('a',1999,'a')||chr(0));
insert into t1(vl) values(lpad('a',1999,'a')||chr(0))
            *
ERROR at line 1:
ORA-01706: user function result value was too large

[email protected]:1521/orcl> insert into t1(vl) values(lpad(chr(1)||chr(2),1333,chr(1)||chr(2)));
1 row created.

[email protected]:1521/orcl> insert into t1(vl) values(lpad(chr(1)||chr(2),1334,chr(1)||chr(2)));
insert into t1(vl) values(lpad(chr(1)||chr(2),1334,chr(1)||chr(2)))
            *
ERROR at line 1:
ORA-01706: user function result value was too large

[email protected]:1521/orcl> commit ;
Commit complete.

[email protected]:1521/orcl> select length(vl),lengthb(vl),dump(substr(vl,1,2),16) c20 from t1;
LENGTH(VL) LENGTHB(VL) C20
---------- ----------- --------------------
      1999        1999 Typ=1 Len=2: 61,61
      1333        1333 Typ=1 Len=2: 1,2

--//特殊情况仅仅插入1333个字符.
--//当然很少在这么长的字段建立索引,而且还是降序索引,并且插入的字符串这么特别。
--//实际上这个根本不是问题,只不过我当时看到索引的类型以及长度时没有反应过来,顺便回头看了原来的文档做的测试。
--//感觉这是一种倒推,不知道oracle为什么做这样的修改,限制了降序索引raw类型最大2000。

标签:.--,降序,vl,t1,SYS,索引,chr,txt,20231105
From: https://www.cnblogs.com/lfree/p/17824970.html

相关文章

  • [20231103]rename IDL_UB1$后使用bbed的恢复3.txt
    [20231103]renameIDL_UB1$后使用bbed的恢复3.txt--//上午解决renameIDL_UB1$后使用bbed的恢复问题,就是涉及到的5个索引4个需要修改,其中一个因为NULL值的缘故,不需要修改。--//主要原因是rename是delete再insertobj$,反过来思考,如果修改时长度等长,我仅仅需要name等于原来的字符......
  • 什么是DNS,A记录,子域名,CNAME别名,MX记录,TXT记录,SRV 记录,TTL值
    DNSDNS,DomainNameSystem或者DomainNameService(域名系统或者域名服务)。域名系统为Internet上的主机分配域名地址和IP地址。由于网络中的计算机都必须有个IP地址,来识别,互相之间才能通信,但让我们记住一大串的IP地址来访问网站显然是不可能的,所以用户使用域名地址,而DNS系统的......
  • 如何新建conda工作环境并安装requirements.txt
    要新建一个conda工作环境并安装requirements.txt文件中的依赖项,您可以按照以下步骤操作:1.打开终端或命令提示符窗口。2.使用以下命令创建一个新的conda环境:     conda create --name myenv  其中,myenv是您想要为环境命名的名称。您可以根据需要自......
  • CMake多个CMakeLists.txt共同合作编译一个C++项目
    一、概述在C++项目比较大或者要根据不同的规则生成不同的执行文件或者动态库/静态库的时候。单独的CMakeLists.txt会变的比较复杂,此时可以利用CMakeLists.txt的父子关系分目录分模块的进行编译及输出。就相当于项目模块化编译参考博客:【大丙课堂】二、具体实现......
  • 记录日志文件 日志文件的内容以Json格式保存到txt文件中
    封装一个方法,传不同的参数,记录不同类型的日志文件,并将大的日志内容,以Json的格式,保存值txt日志文件1.记录操作日志1//记录操作日志2varKeyWord="导入->编辑预算";3newLogService(AccountId).CreateBudgetLog(Common.JsonHelper.ObjToJ......
  • matlab中读取txt数据文件(txt文本文档)
    根据txt文档不同种类介绍不同的读取数据方法一、纯数据文件(没有字母和中文,纯数字)对于这种txt文档,从matalb中读取就简单多了例如test.txt文件,内容为17.901-1.111133.04517.891-1.128633.04517.884-1.134533.045可以在commandwindow中输入loadtest.txt,然后就会产生一......
  • 20231105
    //calculate,collection,currency,facilitate,installment,irrevocable,leeway,minimum,remittance,sightcredit,sightdraftcalculate-计算Calculatemeanstodetermineorestimateanumericalvalueorresultthroughmathematicalorlogicalprocesses.......
  • (Lora训练)(承接midjourney数据修改)(建对应名称txt与删txt内部后缀,括号,数字与转换下划线)Lo
    importosimportredefcreate_txt_from_image():#请求用户输入文件夹地址root_folder=input("请输入图片所在文件夹的完整路径:")#判断路径是否存在ifnotos.path.exists(root_folder):print("路径不存在,请检查输入的地址。")return#用......
  • 【工具包使用】解析txt标注文件
    前言 codeimportosdefparse_onedata(data):print('data:',data)info=data['info']image=data['image']valid=data['valid']rotation=data['rotation']categories=data[&#......
  • 205-java 从资源目录获取txt内容
    java从资源目录获取txt内容publicStringgetCookie(){ClassPathResourceclassPathResource=newClassPathResource("cookie.txt");Stringck=FileUtil.readString(classPathResource.getAbsolutePath(),CharsetUtil.CHARSET_UTF_8);ret......