添加索引是我们经常使用的性能优化手段。在遇到问题的时候,试一试添加索引,看看能不能改变执行计划,是我们分析和解决问题的过
传统的性能优化和调整工作,大都是在系统上线之后,由运维团队进行的。当系统数据量积累到一定程度之后,原有一些隐藏的问题就不断出现。所以,在大数据量、应急场景下进行sql调优,往往是运维团队经常遇到的问题。
添加索引是我们经常使用的性能优化手段。在遇到问题的时候,试一试添加索引,看看能不能改变执行计划,是我们分析和解决问题的过程手段。但是对于大数据表情况下,快速的创建索引是比较困难的事情。这个时候,我们可以利用oracle的virtual index技术。
1、环境介绍和数据准备
virtual index出现的很早。笔者从9i时候的文档资料中,就可以看到virtual index的技术材料。我们还是选择oracle 11gr2进行试验。
sql> select * from v$version;
banner
----------------------------------------------
oracle database 11g enterprise edition release 11.2.0.1.0 - production
pl/sql release 11.2.0.1.0 - production
core11.2.0.1.0production
我们创建数据表t作为实验对象,同时创建正常index和虚拟index。
sql> show user;
user is scott
sql> create table t as select * from dba_objects;
table created
sql> set timing on;
--创建一个普通索引
sql> create index idx_t_owner on t(owner);
index created
executed in0.687seconds
sql> select count(*) from t;
count(*)
----------
72792
executed in 0.015 seconds
我们创建virtual index,需要使用nosegment关键字。
sql> create index idx_t_obj on t(object_id)nosegment;
index created
executed in0.047seconds
sql> exec dbms_stats.gather_table_stats(user,'t',cascade => true);
pl/sql procedure successfully completed
executed in 1.716 seconds
此处我们需要注意一个细节,同样是在7万多基础数据上面创建索引。nosegment虚拟索引使用的时间很短。
2、数据字典层面看virtual index
我们创建了虚拟索引idx_t_obj,又创建了作为参照的idx_t_owner。下面可以从数据字典的层面,,去看看虚拟索引的内容信息。
oracle所有索引信息都记录在dba_indexes视图中。
sql> select index_name, index_type from dba_indexes where wner='scott' and table_name='t';
index_nameindex_type
------------------------------ ---------------------------
idx_t_ownernormal
executed in 0.031 seconds
sql> select segment_name from dba_segments where wner='scott' and segment_name in ('idx_t_owner','idx_t_obj');
segment_name
--------------------------------------------------------------------
idx_t_owner
executed in 0.062 seconds
我们从dba_indexes和dba_segments中,都只能看到普通索引idx_t_owner的信息。而创建的虚拟索引idx_t_obj没有踪迹。nosegment选项可以让我们猜测是没有索引段对象的创建过程。但是,作为字典的dba_indexes信息没有,就让人疑惑。
验证我们的想法,使用dbms_metadata.get_ddl方法,抽取到数据表t的字典定义。其中,我们看到了idx_t_obj的信息。
create index scott.idx_t_obj on scott.t (object_id)
pctfree 10 initrans 2 maxtrans 255nosegment;
create index scott.idx_t_owner on scott.t (owner)
pctfree 10 initrans 2 maxtrans 255 compute statistics
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 ;
相对于idx_t_owner,虚拟索引的定义全文显得很简单,只有nosegment很显眼。
那么,作为万物汇总的dba_objects中呢?
sql> select owner,object_name, object_id, data_object_id, object_type from dba_objects where object_name in ('idx_t_owner','idx_t_obj');
owner object_nameobject_id data_object_id object_type
----- --------------- ---------- -------------- -------------------
scott idx_t_owner7801978019 index
scott idx_t_obj7802078020 index
executed in 0.047 seconds