虚拟索引是在数据字典中定义的伪索引,但是没有相关的索引段。虚拟索引的目的是模拟索引的存储——而不实际创建完整索引。这使得开发者可以创建虚拟索引来查看相关的执行计划,而不必等到索引真正创建后才能查看索引对执行计划的影响,并且不会增加存储空间的使用。如果我们观察到优化器生成了一个昂贵的执行计划并且SQL调优指南建议我们在某些列上创建索引,但是在生产数据库环境中创建索引和测试并不总是可行的。我们需要确保创建的索引不会对数据库中的其他查询产生负面影响,因此可以使用虚拟索引。下面举例说明:1.创建测试表testSQL>createtabletestasselect*fromdba_objects;Tablecreated.2.从表testSQL中查询object_name等于standard的记录>select*fromtestwhereobject_name='STANDARD';OWNER--------------------------------OBJECT_NAME----------------------------------------------------------------------SUBOBJECT_NAMEOBJECT_IDDATA_OBJECT_IDOBJECT_TYPE--------------------------------------------------------------CREATEDLAST_DDL_TIMTIMESTAMPSTATUSTGS----------------------------------------------------SYSSTANDARD888PACKAGE19-APR-1019-APR-102003-04-18:00:00:00VALIDNNNOWNER------------------------------OBJECT_NAME-----------------------------------------------------------------SUBOBJECT_NAMEOBJECT_IDDATA_OBJECT_IDOBJECT_TYPE-------------------------------------------------------------------CREATEDLAST_DDL_TIMTIMESTAMPSTATUSTGS----------------------------------------------------SYSSTANDARD889PACKAGEBODY19-APR-1019-APR-102010-04-19:10:22:58VALIDNNN3。查询上述查询的执行计划SQL>setautotracetraceonlyexplainSQL>select*fromtestwhereobject_name='STANDARD';ExecutionPlan----------------------------------------------------------Planhashvalue:1357081020------------------------------------------------------------------------|Id|操作|名称|行|字节|成本(%CPU)|时间|-------------------------------------------------------------------------------|0|SELECTSTATEMENT||8|1416|155(1)|00:00:02||*1|TABLEACCESSFULL|TEST|8|1416|155(1)|00:00:02|----------------------------------------------------------------------PredicateInformation(identifiedbyoperationid):---------------------------------------------------1-filter("OBJECT_NAME"='STANDARD')注意-----动态采样用于此语句4。在表test的object_name列上创建虚拟索引SQL>createindextest_indexontest(object_name)nosegment;Indexcreated。为了创建虚拟索引,必须在createindex语句中指定nosegment子句,不会创建索引段5.验证虚拟索引不会创建索引段SQL>setautotraceoffSQL>selectindex_namefromdba_indexeswheretable_name='TEST'andindex_name='TEST_INDEX';norowsselectedSQL>colOBJECT_NAMEformata20;SQL>selectobject_name,object_typefromdba_objectswhereobject_name=BEST_INDEX_ECT------_ECT';----------------------------TEST_INDEXINDEX从上面的结果可以看出索引对象已经创建,但是没有索引段已创建。6、重新执行sql查看创建的虚拟索引是否被使用SQL>setautotracetraceonlyexplainSQL>select*fromtestwhereobject_name='STANDARD';ExecutionPlan------------------------------------------------------计划哈希值:1357081020----------------------------------------------------------------|Id|Operation|Name|Rows|Bytes|Cost(%CPU)|Time|--------------------------------------------------------------------|0|SELECTSTATEMENT||8|1416|155(1)|00:00:02||*1|TABLEACCESSFULL|TEST|8|1416|155(1)|00:00:02|----------------------------------------------------------------PredicateInformation(identifiedbyoperationid):----------------------------------------------------1-filter("OBJECT_NAME"='STANDARD')注意------该语句使用的动态采样从上面的执行计划可以清楚的看出未使用创建的虚拟索引。7.为了使用创建的虚拟索引,需要将_USE_NOSEGMENT_INDEXES设置为trueSQL>altersessionset"_USE_NOSEGMENT_INDEXES"=true;Sessionaltered.8.重新执行sql查看创建的虚拟索引是否被使用SQL>setlong900SQL>setlinesize900SQL>select*fromtestwhereobject_name='STANDARD';ExecutionPlan--------------------------------------------------------Planhashvalue:2627321457--------------------------------------------------------------------|Id|Operation|Name|Rows|Bytes|Cost(%CPU)|Time|------------------------------------------------------------------|0|SELECTSTATEMENT||8|1416|5(0)|00:00:01||1|TABLEACCESSBYINDEXROWID|测试|8|1416|5(0)|00:00:01||*2|INDEXRANGESCAN|TEST_INDEX|238||1(0)|00:00:01|---------------------------------------------------------------PredicateInformation(identifiedbyoperationid):--------------------------------------------------2-access("OBJECT_NAME"='STANDARD')注意------dynamicsamplingusedforthisstatement从上面的执行计划可以看出,当设置隐式参数_USE_NOSEGMENT_INDEXES时,优化器将使用使用虚拟索引时需要注意创建的虚拟索引。我们可以分析虚拟索引,但不能重建虚拟索引。如果重建虚拟索引,您将收到ORA-8114:“用户试图更改假索引”错误消息,您可以删除虚拟索引。
