zoukankan      html  css  js  c++  java
  • 在优化SQL语句中使用虚拟索引

    定义:虚拟索引(virtual index) 是指没有创建对应的物理段的索引。

    虚拟索引的目的:是在不损耗主机CPU,IO,磁盘空间去实际创建索引的情况下,来判断一个索引是否能够对SQL优化起到作用。列如我们在优化一条SQL语句的时候,通常会查看需要优化的语句的执行计划,在考虑是否需要在表的某列上建立索引时就可以用到虚拟索引。虚拟索引建立的时候因为其没有消耗主机的相关资源,因此可以在相当快的时间内建立完成。

    下面我们来看一下试验:

    首先建立两张测试表

    create table bigtab as select rownum as id,a.* from sys.all_objects a;  

    create table smalltab as select rownum as id,a.* from  a;  

    create table smalltab as select rownum as id,a.* from sys.all_tables a; 

    多次运行以下语句,以插入多一些测试数据:

    insert into bigtab select ronum as id,a.* from sys.all_objects a;

    insert into smalltab select rownum as id,a.* from sys.all_tables a;    

    查看需要执行语句的执行计划:

    SQL> explain plan for select count(*) from bigtab a,smalltab b where a.object_name=b.table_name;
    
    Explained.
    
    SQL> select * from table(dbms_xplan.display());
    
    PLAN_TABLE_OUTPUT
    --------------------------------------------------------------------------------
    Plan hash value: 3089226980
    
    --------------------------------------------------------------------------------
    | Id  | Operation           | Name     | Rows  | Bytes | Cost (%CPU)| Time     |
    --------------------------------------------------------------------------------
    |   0 | SELECT STATEMENT    |          |     1 |    40 |   518   (1)| 00:00:07 |
    |   1 |  SORT AGGREGATE     |          |     1 |    40 |            |          |
    |*  2 |   HASH JOIN         |          | 99838 |  3899K|   518   (1)| 00:00:07 |
    |   3 |    TABLE ACCESS FULL| SMALLTAB | 15311 |   299K|   172   (0)| 00:00:03 |
    |   4 |    TABLE ACCESS FULL| BIGTAB   | 85284 |  1665K|   345   (1)| 00:00:05 |
    --------------------------------------------------------------------------------
    
    PLAN_TABLE_OUTPUT
    --------------------------------------------------------------------------------
    
    Predicate Information (identified by operation id):
    ---------------------------------------------------
    
       2 - access("A"."OBJECT_NAME"="B"."TABLE_NAME")
    
    16 rows selected.
    


    下面我们在两个表上创建两个虚拟索引,分别在object_name和table_name列上,看看优化器是否会使用这两个索引,以及优化器的成本会如何变化。

    SQL> show parameter _use_nosegment
    SQL> alter session set "_use_nosegment_indexes"=true;
    
    Session altered.
    
    SQL> show parameter _use_nosegment                   
    
    NAME                                 TYPE        VALUE
    ------------------------------------ ----------- ------------------------------
    _use_nosegment_indexes               boolean     TRUE
    SQL> create index big_ind on bigtab(object_name) nosegment;
    
    Index created.
    
    SQL> create index small_ind on smalltab(table_name) nosegment;                
    


    create index语句的NOSEGMENT选项表明这个索引是“虚拟的”-----就是没有与之相关联的实际索引段。如果优化器认为这个索引有用,参数_use_nosegment_indexes将指示数据库可以在执行计划中使用这些索引。下面我们来看看如果真的创建这些索引,它们是否值得使用:

    SQL> explain plan for select count(*) from bigtab a,smalltab b where a.object_name=b.table_name;
    
    Explained.
    
    SQL> select * from table(dbms_xplan.display());                  
    
    PLAN_TABLE_OUTPUT
    --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    Plan hash value: 1254475829
    
    ------------------------------------------------------------------------------------
    | Id  | Operation              | Name      | Rows  | Bytes | Cost (%CPU)| Time     |
    ------------------------------------------------------------------------------------
    |   0 | SELECT STATEMENT       |           |     1 |    40 |    19   (6)| 00:00:01 |
    |   1 |  SORT AGGREGATE        |           |     1 |    40 |            |          |
    |*  2 |   HASH JOIN            |           | 99838 |  3899K|    19   (6)| 00:00:01 |
    |   3 |    INDEX FAST FULL SCAN| SMALL_IND | 15311 |   299K|     9   (0)| 00:00:01 |
    |   4 |    INDEX FAST FULL SCAN| BIG_IND   | 85284 |  1665K|     9   (0)| 00:00:01 |
    ------------------------------------------------------------------------------------
    
    PLAN_TABLE_OUTPUT
    --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    
    Predicate Information (identified by operation id):
    ---------------------------------------------------
    
       2 - access("A"."OBJECT_NAME"="B"."TABLE_NAME")
    
    16 rows selected.
    


    执行计划显示,这两个索引确实被认为有用,优化器估算的成本也下降到19了。所以如果需要优化语句可以建议创建这些索引。

  • 相关阅读:
    Security and Cryptography in Python
    Security and Cryptography in Python
    Security and Cryptography in Python
    Security and Cryptography in Python
    Security and Cryptography in Python
    Security and Cryptography in Python
    基于分布式锁解决定时任务重复问题
    基于Redis的Setnx实现分布式锁
    基于数据库悲观锁的分布式锁
    使用锁解决电商中的超卖
  • 原文地址:https://www.cnblogs.com/snake-hand/p/3157221.html
Copyright © 2011-2022 走看看