最新下载
热门教程
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
Oracle 12c Row limits & Invisible Column学习笔记
时间:2022-06-29 09:40:18 编辑:袖梨 来源:一聚教程网
Oracle 12c 引入了row limits的特性,玩Mysql的人都知道这个,然而Oracle却一直没有这个功能,不过在12c中终于实现了。
SQL> show con_name
CON_NAME
------------------------------
PDBORCL
SQL> create table test_lim as select * from dba_objects;
Table created.
SQL> select count(1) from test_lim;
COUNT(1)
----------
90929
SQL> col owner for a10
SQL> col objecT_name for a30
SQL> select object_id,owner,object_name from test_lim order by 1
2 fetch first 5 rows only;
OBJECT_ID OWNER OBJECT_NAME
---------- ---------- ------------------------------
2 SYS C_OBJ#
3 SYS I_OBJ#
4 SYS TAB$
5 SYS CLU$
6 SYS C_TS#
SQL> l
1 select object_id,owner,object_name from test_lim order by 1
2* fetch first 5 rows only
SQL> /
Execution Plan
----------------------------------------------------------
Plan hash value: 1929006521
---------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)| Time |
---------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 5 | 855 | | 1290 (1)| 00:00:01 |
|* 1 | VIEW | | 5 | 855 | | 1290 (1)| 00:00:01 |
|* 2 | WINDOW SORT PUSHED RANK| | 90929 | 3196K| 4288K| 1290 (1)| 00:00:01 |
| 3 | TABLE ACCESS FULL | TEST_LIM | 90929 | 3196K| | 426 (1)| 00:00:01 |
---------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("from$_subquery$_002"."rowlimit_$$_rownumber"<=5)
2 - filter(ROW_NUMBER() OVER ( ORDER BY "OBJECT_ID")<=5)
而且你还可以查询其中的某几行数据,例如我想查询第100-110 行数据。
SQL> select objecT_id, owner, object_name
2 from test_lim
3 order by 1 offset 110 rows fetch next 10 rows only;
OBJECT_ID OWNER OBJECT_NAME
---------- ---------- ------------------------------
112 SYS I_COLTYPE1
113 SYS I_COLTYPE2
114 SYS SUBCOLTYPE$
115 SYS I_SUBCOLTYPE1
116 SYS NTAB$
117 SYS I_NTAB1
118 SYS I_NTAB2
119 SYS I_NTAB3
120 SYS REFCON$
121 SYS I_REFCON1
10 rows selected.
注意,它这里的offset是根据行号(rownum来的)。如果你这样觉得不明白,这样查询就明白了,如下:
SQL> select rownum,a.objecT_id, a.owner, a.object_name
2 from test_lim a
3 order by 1 offset 110 rows fetch next 10 rows only;
ROWNUM OBJECT_ID OWNER OBJECT_NAME
---------- ---------- ---------- ------------------------------
111 112 SYS I_COLTYPE1
112 113 SYS I_COLTYPE2
113 114 SYS SUBCOLTYPE$
114 115 SYS I_SUBCOLTYPE1
115 116 SYS NTAB$
116 117 SYS I_NTAB1
117 118 SYS I_NTAB2
118 119 SYS I_NTAB3
119 120 SYS REFCON$
120 121 SYS I_REFCON1
10 rows selected.
除了前面fetch和offset用法之外,还有一个percent选项,如下:
SQL> select count(1) from (
2 select objecT_id, owner, object_name
3 from test_lim a order by 1
4 fetch first 1 percent rows only);
COUNT(1)
----------
910
SQL> select objecT_id, owner, object_name
2 from test_lim a
3 order by 1 fetch first 0.01 percent rows only;
OBJECT_ID OWNER OBJECT_NAME
---------- ---------- ------------------------------
2 SYS C_OBJ#
3 SYS I_OBJ#
4 SYS TAB$
5 SYS CLU$
6 SYS C_TS#
7 SYS I_TS#
8 SYS C_FILE#_BLOCK#
9 SYS I_FILE#_BLOCK#
10 SYS C_USER#
11 SYS I_USER#
10 rows selected.
我们可以返回指定比例的数据,注意,Oracle这里是取整的,而且不是四舍五入的原则。
SQL> set autot traceonly
SQL> l
1 select objecT_id, owner, object_name
2 from test_lim a
3* order by 1 fetch first 0.01 percent rows only
SQL> /
10 rows selected.
Execution Plan
----------------------------------------------------------
Plan hash value: 547893470
----------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)| Time |
----------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 90929 | 15M| | 1290 (1)| 00:00:01 |
|* 1 | VIEW | | 90929 | 15M| | 1290 (1)| 00:00:01 |
| 2 | WINDOW SORT | | 90929 | 3196K| 4288K| 1290 (1)| 00:00:01 |
| 3 | TABLE ACCESS FULL| TEST_LIM | 90929 | 3196K| | 426 (1)| 00:00:01 |
----------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("from$_subquery$_002"."rowlimit_$$_rownumber"<=CEIL("from$_subquer
y$_002"."rowlimit_$$_total"*0.01/100))
可以清楚的看到Oracle的过程,其实是进行了一个复杂的filter操作。
+++++++++ Invisible column +++++++++++++
在Oracle 11g版本中,引入了invisible Index特性,在12c中更进一步,可以让column也不可见,即invisible column特性。
SQL> create table test_visible as select owner,object_id
2 from dba_objects where object_id < 10;
Table created.
SQL> alter table test_visible modify (owner invisible);
Table altered.
SQL> desc test_visible
Name Null? Type
------------------------------ -------- --------------------------------------------
OBJECT_ID NUMBER
SQL>
SQL> select * from test_visible where rownum < 3;
OBJECT_ID
----------
9
8
可以看到,当column被修改为invisible(不可见)之后,你desc都无法查看该column的信息,当然select查询也不会返回该列的数据。
SQL> alter table test_visible modify (owner visible);
Table altered.
SQL> select * from test_visible where rownum < 3;
OBJECT_ID OWNER
---------- ----------
9 SYS
8 SYS
SQL> alter table test_visible modify (owner invisible);
Table altered.
SQL> select owner,table_name,column_name,HIDDEN_COLUMN,IDENTITY_COLUMN
2 from dba_tab_cols where owner='ROGER' and table_name='TEST_VISIBLE';
OWNER TABLE_NAME COLUMN_NAME HID IDE
---------- -------------------- -------------------- --- ---
ROGER TEST_VISIBLE OWNER YES NO
ROGER TEST_VISIBLE OBJECT_ID NO NO
SQL> insert into test_visible(objecT_id,owner) values(99999,'killdb.com');
1 row created.
SQL> commit;
Commit complete.
SQL> select * from test_visible;
OBJECT_ID
----------
9
8
7
6
5
4
3
2
99999
9 rows selected.
SQL>
当column被设置为invisible 之后,不代表该列的数据就变化了,我们仍然可以进行insert操作。
这里我比较好奇Oracle是在怎么来实现的,想想也应该是通过修改数据字典col$的某个字典属性来实现,检查发现果然是这样的。
Oracle 12c 版本中col$ 数据字典表的结构和column名称的解释如下:
create table col$ /* column table */
( obj# number not null, /* object number of base object */
col# number not null, /* column number as created */
segcol# number not null, /* column number in segment */
segcollength number not null, /* length of the segment column */
offset number not null, /* offset of column */
name varchar2("M_IDEN") not null, /* name of column */
type# number not null, /* data type of column */
/* for ADT column, type# = DTYADT */
length number not null, /* length of column in bytes */
fixedstorage number not null, /* flags: 0x01 = fixed, 0x02 = read-only */
precision# number, /* precision */
scale number, /* scale */
null$ number not null, /* 0 = NULLs permitted, */
/* > 0 = no NULLs permitted */
deflength number, /* default value expression text length */
default$ long, /* default value expression text */
/*
* If a table T(c1, addr, c2) contains an ADT column addr which is stored
* exploded, the table will be internally stored as
* T(c1, addr, C0003$, C0004$, C0005$, c2)
* Of these, only c1, addr and c2 are user visible columns. Thus, the
* user visible column numbers for (c1, addr, C0003$, C0004$, C0005$, c2)
* will be 1,2,0,0,0,3. And the corresponding internal column numbers will
* be 1,2,3,4,5,6.
*
* Some dictionary tables like icol$, ccol$ need to contain intcol# so
* that we can have indexes and constraints on ADT attributes. Also, these
* tables also need to contain col# to maintain backward compatibility.
* Most of these tables will need to be accessed by col#, intcol# so
* indexes are created on them based on (obj#, col#) and (obj#, intcol#).
* Indexes based on col# have to be non-unique if ADT attributes might
* appear in the table. Indexes based on intcol# can be unique.
*/
intcol# number not null, /* internal column number */
property number not null, /* column properties (bit flags): */
/* 0x0001 = 1 = ADT attribute column */
/* 0x0002 = 2 = OID column */
/* 0x0004 = 4 = nested table column */
/* 0x0008 = 8 = virtual column */
/* 0x0010 = 16 = nested table's SETID$ column */
/* 0x0020 = 32 = hidden column */
/* 0x0040 = 64 = primary-key based OID column */
/* 0x0080 = 128 = column is stored in a lob */
/* 0x0100 = 256 = system-generated column */
/* 0x0200 = 512 = rowinfo column of typed table/view */
/* 0x0400 = 1024 = nested table columns setid */
/* 0x0800 = 2048 = column not insertable */
/* 0x1000 = 4096 = column not updatable */
/* 0x2000 = 8192 = column not deletable */
/* 0x4000 = 16384 = dropped column */
/* 0x8000 = 32768 = unused column - data still in row */
/* 0x00010000 = 65536 = virtual column */
/* 0x00020000 = 131072 = place DESCEND operator on top */
/* 0x00040000 = 262144 = virtual column is NLS dependent */
/* 0x00080000 = 524288 = ref column (present as oid col) */
/* 0x00100000 = 1048576 = hidden snapshot base table column */
/* 0x00200000 = 2097152 = attribute column of a user-defined ref */
/* 0x00400000 = 4194304 = export hidden column,RLS on hidden col */
/* 0x00800000 = 8388608 = string column measured in characters */
/* 0x01000000 = 16777216 = virtual column expression specified */
/* 0x02000000 = 33554432 = typeid column */
/* 0x04000000 = 67108864 = Column is encrypted */
/* 0x20000000 = 536870912 = Column is encrypted without salt */
/* 0x000800000000 = 34359738368 = default with sequence */
/* 0x001000000000 = 68719476736 = default on null */
/* 0x002000000000 = 137438953472 = generated always identity column */
/* 0x004000000000 = 274877906944 = generated by default identity col */
/* 0x080000000000 = 8796093022208 = Column is sensitive */
/* The spares may be used as the column's NLS character set,
* the number of distinct column values, and the column's domain.
*/
/* the universal character set id maintained by NLS group */
charsetid number, /* NLS character set id */
/*
* charsetform
*/
charsetform number,
/* 1 = implicit: for CHAR, VARCHAR2, CLOB w/o a specified set */
/* 2 = nchar: for NCHAR, NCHAR VARYING, NCLOB */
/* 3 = explicit: for CHAR, etc. with "CHARACTER SET ..." clause */
/* 4 = flexible: for PL/SQL "flexible" parameters */
evaledition# number, /* evaluation edition */
unusablebefore# number, /* unusable before edition */
unusablebeginning# number, /* unusable beginning with edition */
spare1 number, /* fractional seconds precision */
spare2 number, /* interval leading field precision */
spare3 number, /* maximum number of characters in string */
spare4 varchar2(1000), /* NLS settings for this expression */
spare5 varchar2(1000),
spare6 date,
spare7 number,
spare8 number
)
大家注意看其中的 property 列的属性,可以发现其中有hidden column的说明,这显然就是invisible的意思。
下面我们可以通过查询来观察下其变化:
SQL> select owner,objecT_id from dba_objects where object_name='TEST_VISIBLE';
OWNER OBJECT_ID
---------- ----------
ROGER 91829
SQL> select obj#,col#,name,intcol#,property from col$ where obj#=91829;
OBJ# COL# NAME INTCOL# PROPERTY
---------- ---------- ------------------------------ ---------- -------------------
91829 0 OWNER 1 17179883552
91829 1 OBJECT_ID 2 14336
SQL> SELECT name, col#, intcol#, segcol#, TO_CHAR(property, 'XXXXXXXXXXXX')
2 FROM sys.col$
3 WHERE obj# = (SELECT obj# FROM sys.obj$ WHERE name = 'TEST_VISIBLE');
NAME COL# INTCOL# SEGCOL# TO_CHAR(PROPE
------------------------------ ---------- ---------- ---------- -------------
OWNER 0 1 1 400003820
OBJECT_ID 1 2 2 3800
SQL> alter table test_visible modify (owner VISIBLE);
Table altered.
SQL> SELECT name, col#, intcol#, segcol#, TO_CHAR(property, 'XXXXXXXXXXXX')
2 FROM sys.col$
3 WHERE obj# = (SELECT obj# FROM sys.obj$ WHERE name = 'TEST_VISIBLE');
NAME COL# INTCOL# SEGCOL# TO_CHAR(PROPE
------------------------------ ---------- ---------- ---------- -------------
OWNER 2 1 1 3800
OBJECT_ID 1 2 2 3800
SQL>
可以看到,我们的猜测是没错的,如果你通dbms_metadata去获取table的定义,其实也能发现对于隐藏列Oracle加了一个invisible关键字:
SQL> select dbms_metadata.get_ddl('TABLE','TEST_VISIBLE') from dual;
DBMS_METADATA.GET_DDL('TABLE','TEST_VISIBLE')
--------------------------------------------------------------------------------
CREATE TABLE "ROGER"."TEST_VISIBLE"
( "OWNER" VARCHAR2(128) INVISIBLE,
"OBJECT_ID" NUMBER
) SEGMENT CREATION IMMEDIATE
PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255
NOCOMPRESS LOGGING
STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT)
TABLESPACE "USERS"
后面有空还会继续研究和分享Oracle 12c的其他内容,这仅仅是个开始!
相关文章
- 炉石传说血DK卡组怎么样 炉石传说血DK卡组推荐介绍 11-05
- 咒术回战幻影夜行官网在哪里 咒术回战幻影夜行官网地址介绍 11-05
- 蚂蚁庄园今天答题答案2024年10月26日 11-05
- 以闪亮之名变装物语甜趣篇怎么玩 11-05
- 闪耀暖暖永夜禁锢怎么玩 11-05
- 闪耀暖暖永夜禁锢怎么玩 闪耀暖暖永夜禁锢活动介绍 11-05