前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【DB笔试面试560】在Oracle中,虚拟列索引(Virtual Column Indexes)的作用是什么?

【DB笔试面试560】在Oracle中,虚拟列索引(Virtual Column Indexes)的作用是什么?

作者头像
小麦苗DBA宝典
发布2019-09-29 15:32:13
1.1K0
发布2019-09-29 15:32:13
举报

题目部分

在Oracle中,虚拟列索引(Virtual Column Indexes)的作用是什么?

答案部分

在Oracle 11g之前的版本中,如果需要使用表达式或者一些计算公式,那么需要创建数据库视图;如果需要在这个视图上使用索引,那么会在表上创建基于函数的索引。虚拟列是Oracle 11g新引入的一项技术,虚拟列是一个表达式,在运行时计算,不存储在数据库中,不能更新虚拟列的值。使用虚拟列有如下好处:

① 可以收集虚拟列的统计信息,为CBO提供一定的采样分析。

② 可以在WHERE后面使用虚拟列作为选择条件。

③ 只在一处定义,不存储多余数据,查询时动态生成数据。

定义一个虚拟列的语法如下所示:

代码语言:javascript
复制
column_name [datatype] [GENERATED ALWAYS] AS [expression] [VIRTUAL]

下面给出虚拟列及虚拟列索引的语法示例:

代码语言:javascript
复制
CREATE TABLE T_VC_20170518_LHR2(VC_ID   NUMBER, VC_COUNT  NUMBER, VC_ALL  GENERATED ALWAYS AS ( VC_ID + VC_COUNT ) VIRTUAL);
CREATE INDEX VC_STATUS_IND2 ON T_VC_20170518_LHR2(VC_ALL);

虚拟列有如下特点:

① 在虚拟列的表达式中,可以包括同表的其它列、常量、SQL函数,甚至可以包括一些用户自定义的PL/SQL函数。

② 可以为虚拟列创建索引,称为虚拟列索引(实际上,Oracle为其创建的是函数索引),不能显式地为虚拟列创建函数索引。

③ 可以通过视图DBA_TAB_COLS的DATA_DEFAULT列来查询虚拟列的表达式,当创建了虚拟列索引(其实是一种函数索引)后,在视图DBA_IND_EXPRESSIONS中不能查询索引列。

④ 虚拟列的值并不是真实存在的,只有在用到时,才根据表达式计算出虚拟列的值,磁盘上并不存放虚拟列的数据。

⑤ 由于虚拟列的值由Oracle根据表达式自动计算得出,所以,虚拟列可以用在SELECT,UPDATE,DELETE语句的WHERE条件中,但是不能用于DML语句。

⑥ 可以基于虚拟列来做分区。

⑦ 可以在虚拟列上创建约束(例如主键)。

⑧ 只能在堆组织表(Heap-Organized Table,普通表)上创建虚拟列,不能在索引组织表、外部表、临时表上创建虚拟列。

⑨ 虚拟列值只能是标量,不能是其它类型(例如集合、LOB、RAW等类型)。

⑩ 可以把虚拟列当做分区关键字建立分区表,这是Oracle 11g的另一新特性称为虚拟列分区。

⑪ 在已经创建的表中增加虚拟列时,若没有指定虚拟列的字段类型,则Oracle会根据关键字“GENERATED ALWAYS AS”后面的表达式计算的结果自动设置该字段的数据类型。

⑫ 表达式中的所有列必须在同一张表。

⑬ 虚拟列表达式不能使用其它虚拟列。

下面给出虚拟列及虚拟列索引的使用示例:

代码语言:javascript
复制
LHR@orclasm > CREATE TABLE T_VC_20170518_LHR(  
  2    VC_ID   NUMBER,  
  3    VC_COUNT  NUMBER,  
  4    VC_STATUS  GENERATED ALWAYS AS   
  5    (CASE  WHEN  VC_COUNT <= 100 THEN 'GETTING LOW'  
  6          WHEN  VC_COUNT > 100  THEN 'OKAY'  
  7    END)  
  8  );
Table created.
LHR@orclasm > DESC T_VC_20170518_LHR
 Name                                      Null?    Type
 ----------------------------------------- -------- ----------------------------
 VC_ID                                              NUMBER
 VC_COUNT                                           NUMBER
 VC_STATUS                                          VARCHAR2(11)
LHR@orclasm > insert into T_VC_20170518_LHR (VC_ID, VC_COUNT) values (1, 100);
1 row created.
LHR@orclasm > SELECT * FROM T_VC_20170518_LHR;
     VC_ID   VC_COUNT VC_STATUS
---------- ---------- -----------
         1        100 GETTING LOW
LHR@orclasm > ALTER TABLE T_VC_20170518_LHR ADD  VC_COMM GENERATED ALWAYS AS(VC_COUNT * 0.1) VIRTUAL; 
Table altered.
LHR@orclasm > DESC T_VC_20170518_LHR
 Name                                      Null?    Type
 ----------------------------------------- -------- ----------------------------
 VC_ID                                              NUMBER
 VC_COUNT                                           NUMBER
 VC_STATUS                                          VARCHAR2(11)
 VC_COMM                                            NUMBER
LHR@orclasm > SELECT * FROM T_VC_20170518_LHR;
     VC_ID   VC_COUNT VC_STATUS      VC_COMM
---------- ---------- ----------- ----------
         1        100 GETTING LOW         10
LHR@orclasm > alter table T_VC_20170518_LHR modify VC_STATUS generated always as(  
  2  case when VC_COUNT <= 50 then 'NEED MORE'  
  3  when VC_COUNT >50 and VC_COUNT <=200 then 'GETTING LOW'  
  4  when VC_COUNT > 200 then 'OKAY'  
  5  end);
Table altered.
LHR@orclasm > update T_VC_20170518_LHR set VC_COUNT=100 where VC_STATUS='OKAY';
0 rows updated.
LHR@orclasm > set line 9999
LHR@orclasm > col data_type format a10
LHR@orclasm > select table_name,COLUMN_NAME,data_type,data_default,VIRTUAL_COLUMN from user_tab_cols where table_name='T_VC_20170518_LHR';
TABLE_NAME                     COLUMN_NAME                    DATA_TYPE  DATA_DEFAULT                                                                     VIR
------------------------------ ------------------------------ ---------- -------------------------------------------------------------------------------- ---
T_VC_20170518_LHR              VC_ID                          NUMBER                                                                                      NO
T_VC_20170518_LHR              VC_COUNT                       NUMBER                                                                                      NO
T_VC_20170518_LHR              VC_STATUS                      VARCHAR2   CASE  WHEN "VC_COUNT"<=50 THEN 'NEED MORE' WHEN ("VC_COUNT">50 AND "VC_COUNT"<=2 YES
T_VC_20170518_LHR              VC_COMM                        NUMBER     "VC_COUNT"*0.1                                                                   YES
T_VC_20170518_LHR              VC_COMM2                       NUMBER     "VC_COUNT"*0.2                                                                   YES
LHR@orclasm > alter table T_VC_20170518_LHR add  (VC_comm2  as(VC_COUNT * 0.2) VIRTUAL);
Table altered.
LHR@orclasm > create index VC_STATUS_ind on T_VC_20170518_LHR(VC_STATUS);
Index created.
LHR@orclasm > select table_name,index_name,INDEX_TYPE from user_indexes where table_name='T_VC_20170518_LHR';
TABLE_NAME                     INDEX_NAME                     INDEX_TYPE
------------------------------ ------------------------------ ---------------------------
T_VC_20170518_LHR              VC_STATUS_IND                  FUNCTION-BASED NORMAL

& 说明:

有关虚拟列的更多内容可以参考我的BLOG:http://blog.itpub.net/26736162/viewspace-2139258/

其它索引

应用程序域索引(Application Domain Indexes)是由用户为一个特定的应用程序域中的数据创建的。其物理索引不需要使用传统的索引结构,可以存储为Oracle数据库表,或外部文件。应用程序域索引是一个特定于应用程序的自定义索引。

对于B-Tree簇索引(B-Tree Cluster Indexes)和哈希聚簇索引(Hash Cluster Indexes)本书不再详解,对此感兴趣的读者可以参考相关的官方文档。

本文选自《Oracle程序员面试笔试宝典》,作者:李华荣。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-05-13,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 DB宝 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
数据库
云数据库为企业提供了完善的关系型数据库、非关系型数据库、分析型数据库和数据库生态工具。您可以通过产品选择和组合搭建,轻松实现高可靠、高可用性、高性能等数据库需求。云数据库服务也可大幅减少您的运维工作量,更专注于业务发展,让企业一站式享受数据上云及分布式架构的技术红利!
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档