Oracle 12c 新特性 --- 同一列上可建多个索引

概念

Multiple indexes can be created on the same set of columns as long as some characteristic is different. Qualifying characteristics are:

•	B-tree versus bitmap
•	Different partitioning strategies
•	Unique versus non-unique
•	
Providing the capability to create multiple indexes on the same set of columns enables transparent and seamless application migrations without the need to drop an existing index and re-create it with different attributes.

可以在同一组列上创建多个索引,只要某些特征是不同的。限制的特点是:
b -树和位图
不同的分区策略
独特的和非唯一
提供在同一组列上创建多个索引的功能,可以实现透明和无缝的应用迁移,而不需要删除现有索引并重新创建具有不同属性的索引。

当索引以某种方式不同时,可以在同一列上创建多个索引。例如,您可以在同一组列上创建一个b - tree索引和位图索引。

当在同一组列上有多个索引时,这些索引中只有一个可以同时可见,任何其他索引都必须是不可见的。

您可以在同一组列上创建不同的索引,因为它们提供了满足您需求的灵活性。您还可以在同一组列上创建多个索引,以执行应用程序迁移,而不删除现有索引,并使用不同的属性重新创建它。

不同类型的索引在不同的场景中是有用的。例如,b - tree索引通常在有许多并发事务的联机事务处理(OLTP)系统中使用,而位图索引通常用于数据仓库系统中,这些系统主要用于查询。类似地,局部和全局分区索引在不同的场景中是有用的。局部分区索引易于管理,因为分区维护操作会自动应用于它们。当您希望索引的分区方案与表的分区方案不同时,全局分区索引非常有用。

 

实验

Oracle 12c允许同一组列上的多个索引,只提供一个索引是可见的,并且所有索引在某种程度上都是不同的。
[leo@www.cndba.cn ~]$ sqlplus "/as sysdba"

SQL*Plus: Release 12.1.0.2.0 Production on Sat Aug 19 22:39:08 2017

Copyright (c) 1982, 2014, Oracle.  All rights reserved.


Connected to:
Oracle Database 12c Enterprise Edition Release 12.1.0.2.0 - 64bit Production
With the Partitioning, OLAP, Advanced Analytics and Real Application Testing options

SQL> alter session set container=pdbcndba;

Session altered.

SQL> conn test/test@pdbcndba
Connected.
1 普通表建索引
1.1 创建表t1
SQL> DROP TABLE t1 PURGE;

Table dropped.

SQL> CREATE TABLE t1 (
  id            NUMBER,
  description   VARCHAR2(50),
  created_date  DATE
);

Table created.

SQL> INSERT INTO t1 VALUES (1, 't1 ONE', TO_DATE('01/07/2014', 'DD/MM/YYYY'));
1 row created.
SQL>INSERT INTO t1 VALUES (2, 't1 TWO', TO_DATE('01/07/2015', 'DD/MM/YYYY'));
1 row created.
SQL>INSERT INTO t1 VALUES (3, 't1 THREE', TO_DATE('01/07/2016', 'DD/MM/YYYY')); 
1 row created.
1.2 创建第一个索引
SQL> CREATE INDEX t1_idx1 ON t1(created_date) VISIBLE;

Index created.
1.3 如果我们尝试在同一列上创建一个不可见的索引,它失败了,因为它具有相同的属性,即现有的索引。
SQL> CREATE INDEX t1_idx2 ON t1(created_date) INVISIBLE;
CREATE INDEX t1_idx2 ON t1(created_date) INVISIBLE
                           *
ERROR at line 1:
ORA-01408: such column list already indexed
 1.4 如果我们改变它,比如使它成为一个位图索引,它就能工作。
SQL> CREATE BITMAP INDEX t1_idx3 ON t1(created_date) INVISIBLE;

Index created.

2 分区表建索引
2.1 创建分区表
SQL> DROP TABLE t1 PURGE;

Table dropped.

SQL> CREATE TABLE t1 (
  id            NUMBER,
  description   VARCHAR2(50),
  created_date  DATE
)
PARTITION BY RANGE (created_date) (
  PARTITION part_2014 VALUES LESS THAN (TO_DATE('01/01/2015', 'DD/MM/YYYY')) TABLESPACE users,
  PARTITION part_2015 VALUES LESS THAN (TO_DATE('01/01/2016', 'DD/MM/YYYY')) TABLESPACE users,
  PARTITION part_2016 VALUES LESS THAN (TO_DATE('01/01/2017', 'DD/MM/YYYY')) TABLESPACE users
);

Table created.

SQL> INSERT INTO t1 VALUES (1, 't1 ONE', TO_DATE('01/07/2014', 'DD/MM/YYYY'));
1 row created.
SQL> INSERT INTO t1 VALUES (2, 't1 TWO', TO_DATE('01/07/2015', 'DD/MM/YYYY'));
1 row created.
SQL> INSERT INTO t1 VALUES (3, 't1 THREE', TO_DATE('01/07/2016', 'DD/MM/YYYY'));
1 row created.

SQL> COMMIT;

Commit complete.
2.2 创建全局索引
SQL> CREATE INDEX t1_idx1 ON t1(created_date) GLOBAL VISIBLE;

Index created.
2.3 创建一些带有不同 partitioning schemes的索引。
SQL> CREATE INDEX t1_idx2 ON t1(created_date) GLOBAL
PARTITION BY RANGE (created_date) (
  PARTITION t1_p1 VALUES LESS THAN (TO_DATE('01/01/2015', 'DD/MM/YYYY')) TABLESPACE users,
  PARTITION t1_p2 VALUES LESS THAN (TO_DATE('01/01/2016', 'DD/MM/YYYY')) TABLESPACE users,
  PARTITION t1_p3 VALUES LESS THAN (MAXVALUE) TABLESPACE users
)
INVISIBLE;

Index created.

SQL> CREATE INDEX t1_idx3 ON t1(created_date) LOCAL INVISIBLE;

Index created.
--创建位图索引
SQL> CREATE BITMAP INDEX t1_idx4 ON t1(created_date) LOCAL INVISIBLE;

Index created.

在相同的列上有多个索引允许您快速切换它们,从而更快地测试各种索引的影响。请记住,在表上有太多索引的DML性能会受到影响,因此这应该是一个短期的情况。 下面的示例使用了在前一节中创建的分区表和相关索引。
--检查可见性的索引。
SQL> COLUMN index_name FORMAT A10
SQL> COLUMN index_type FORMAT A10
SQL> COLUMN partitioned FORMAT A12
SQL> COLUMN locality FORMAT A8
SQL> COLUMN visibility FORMAT A10
SQL> SELECT a.index_name,
       a.index_type,
       a.partitioned,
       b.partitioning_type,
       b.locality,
       a.visibility
FROM   user_indexes a
       LEFT OUTER JOIN user_part_indexes b ON a.index_name = b.index_name
ORDER BY index_name;

INDEX_NAME INDEX_TYPE PARTITIONED  PARTITION LOCALITY VISIBILITY
---------- ---------- ------------ --------- -------- ----------
T1_IDX1    NORMAL     NO			                   VISIBLE
T1_IDX2    NORMAL     YES	        RANGE     GLOBAL   INVISIBLE
T1_IDX3    NORMAL     YES	        RANGE     LOCAL    INVISIBLE
T1_IDX4    BITMAP     YES	        RANGE     LOCAL    INVISIBLE
--测试索引使用,切换索引可见性和测试。
SQL> SET AUTOTRACE TRACE EXPLAIN

SQL> set line 500
SQL> SELECT *
FROM   t1
WHERE created_date = TO_DATE('01/07/2014', 'DD/MM/YYYY');  2    3  

Execution Plan
----------------------------------------------------------
Plan hash value: 1106166644

----------------------------------------------------------------------------------------------------------------------
| Id  | Operation				   | Name    | Rows  | Bytes | Cost (%CPU)| Time     | Pstart| Pstop |
----------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT			   |	     |	   1 |	  49 |	   1   (0)| 00:00:01 |	     |	     |
|   1 |  TABLE ACCESS BY GLOBAL INDEX ROWID BATCHED| T1      |	   1 |	  49 |	   1   (0)| 00:00:01 |	   1 |	   1 |
|*  2 |   INDEX RANGE SCAN			   | T1_IDX1 |	   1 |	     |	   1   (0)| 00:00:01 |	     |	     |
----------------------------------------------------------------------------------------------------------------------


SQL> SET AUTOTRACE OFF
SQL> ALTER INDEX t1_idx1 INVISIBLE;

Index altered.

SQL> ALTER INDEX t1_idx2 VISIBLE;

Index altered.

SQL> SELECT a.index_name,
       a.index_type,
       a.partitioned,
       b.partitioning_type,
       b.locality,
       a.visibility
FROM   user_indexes a
       LEFT OUTER JOIN user_part_indexes b ON a.index_name = b.index_name
ORDER BY index_name;  2    3    4    5    6    7    8    9  

INDEX_NAME INDEX_TYPE PARTITIONED  PARTITION LOCALITY VISIBILITY
---------- ---------- ------------ --------- -------- ----------
T1_IDX1    NORMAL     NO			                   INVISIBLE
T1_IDX2    NORMAL     YES	        RANGE     GLOBAL   VISIBLE
T1_IDX3    NORMAL     YES	        RANGE     LOCAL    INVISIBLE
T1_IDX4    BITMAP     YES	        RANGE     LOCAL    INVISIBLE

SQL> SET AUTOTRACE TRACE EXPLAIN
SQL> SELECT *
FROM   t1
WHERE created_date = TO_DATE('01/07/2014', 'DD/MM/YYYY');  

Execution Plan
----------------------------------------------------------
Plan hash value: 3769679070

-----------------------------------------------------------------------------------------------------------------------
| Id  | Operation				    | Name    | Rows  | Bytes | Cost (%CPU)| Time     | Pstart| Pstop |
-----------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT			    |	      |     1 |    49 |     1	(0)| 00:00:01 |       |       |
|   1 |  PARTITION RANGE SINGLE 		              |     1 |    49 |     1	(0)| 00:00:01 |     1 |     1 |
|   2 |   TABLE ACCESS BY GLOBAL INDEX ROWID BATCHED| T1      |     1 |    49 |     1	(0)| 00:00:01 |     1 |     1 |
|*  3 |    INDEX RANGE SCAN			    | T1_IDX2 |     1 |       |     1	(0)| 00:00:01 |     1 |     1 |
-----------------------------------------------------------------------------------------------------------------------

SQL> SET AUTOTRACE OFF
SQL> ALTER INDEX t1_idx2 INVISIBLE;

Index altered.

SQL> ALTER INDEX t1_idx3 VISIBLE;

Index altered.

SQL> SELECT a.index_name,
       a.index_type,
       a.partitioned,
       b.partitioning_type,
       b.locality,
       a.visibility
FROM   user_indexes a
       LEFT OUTER JOIN user_part_indexes b ON a.index_name = b.index_name
ORDER BY index_name; 

INDEX_NAME INDEX_TYPE PARTITIONED  PARTITION LOCALITY VISIBILITY
---------- ---------- ------------ --------- -------- ----------
T1_IDX1    NORMAL     NO			                   INVISIBLE
T1_IDX2    NORMAL     YES	        RANGE     GLOBAL   INVISIBLE
T1_IDX3    NORMAL     YES	        RANGE     LOCAL    VISIBLE
T1_IDX4    BITMAP     YES	        RANGE     LOCAL    INVISIBLE

SQL> SET AUTOTRACE TRACE EXPLAIN
SQL> SELECT *
FROM   t1
WHERE created_date = TO_DATE('01/07/2014', 'DD/MM/YYYY');

Execution Plan
----------------------------------------------------------
Plan hash value: 597299548

----------------------------------------------------------------------------------------------------------------------
| Id  | Operation				   | Name    | Rows  | Bytes | Cost (%CPU)| Time     | Pstart| Pstop |
----------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT			   |	     |	   1 |	  49 |	   1   (0)| 00:00:01 |	     |	     |
|   1 |  PARTITION RANGE SINGLE 		   |	     |	   1 |	  49 |	   1   (0)| 00:00:01 |	   1 |	   1 |
|   2 |   TABLE ACCESS BY LOCAL INDEX ROWID BATCHED| T1      |	   1 |	  49 |	   1   (0)| 00:00:01 |	   1 |	   1 |
|*  3 |    INDEX RANGE SCAN			   | T1_IDX3 |	   1 |	     |	   1   (0)| 00:00:01 |	   1 |	   1 |
----------------------------------------------------------------------------------------------------------------------
SQL> SET AUTOTRACE OFF

SQL> ALTER INDEX t1_idx3 INVISIBLE;

Index altered.

SQL> ALTER INDEX t1_idx4 VISIBLE;

Index altered.


SQL> SELECT a.index_name,
       a.index_type,
       a.partitioned,
       b.partitioning_type,
       b.locality,
       a.visibility
FROM   user_indexes a
       LEFT OUTER JOIN user_part_indexes b ON a.index_name = b.index_name
ORDER BY index_name; 

INDEX_NAME INDEX_TYPE PARTITIONED  PARTITION LOCALITY VISIBILITY
---------- ---------- ------------ --------- -------- ----------
T1_IDX1    NORMAL     NO			                   INVISIBLE
T1_IDX2    NORMAL     YES	        RANGE     GLOBAL   INVISIBLE
T1_IDX3    NORMAL     YES	        RANGE     LOCAL    INVISIBLE
T1_IDX4    BITMAP     YES	        RANGE     LOCAL    VISIBLE

SQL> SET AUTOTRACE TRACE EXPLAIN
SQL> SELECT *
FROM   t1
WHERE created_date = TO_DATE('01/07/2014', 'DD/MM/YYYY'); 

Execution Plan
----------------------------------------------------------
Plan hash value: 2425632905

----------------------------------------------------------------------------------------------------------------------
| Id  | Operation				   | Name    | Rows  | Bytes | Cost (%CPU)| Time     | Pstart| Pstop |
----------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT			   |	     |	   1 |	  49 |	  15   (0)| 00:00:01 |	     |	     |
|   1 |  PARTITION RANGE SINGLE 		   |	     |	   1 |	  49 |	  15   (0)| 00:00:01 |	   1 |	   1 |
|   2 |   TABLE ACCESS BY LOCAL INDEX ROWID BATCHED| T1      |	   1 |	  49 |	  15   (0)| 00:00:01 |	   1 |	   1 |
|   3 |    BITMAP CONVERSION TO ROWIDS		   |	     |	     |	     |		  |	     |	     |	     |
|*  4 |     BITMAP INDEX SINGLE VALUE		   | T1_IDX4 |	     |	     |		  |	     |	   1 |	   1 |
----------------------------------------------------------------------------------------------------------------------

SQL> SET AUTOTRACE OFF


3 OPTIMIZER_USE_INVISIBLE_INDEXES
与任何可用的不可见的索引一样,将优化的use_invisible_indexes参数设置为TRUE,就可以为优化器提供这些参数。
SQL> SELECT a.index_name,
       a.index_type,
       a.partitioned,
       b.partitioning_type,
       b.locality,
       a.visibility
FROM   user_indexes a
       LEFT OUTER JOIN user_part_indexes b ON a.index_name = b.index_name
ORDER BY index_name; 

INDEX_NAME INDEX_TYPE PARTITIONED  PARTITION LOCALITY VISIBILITY
---------- ---------- ------------ --------- -------- ----------
T1_IDX1    NORMAL     NO			                  INVISIBLE
T1_IDX2    NORMAL     YES	       RANGE     GLOBAL   INVISIBLE
T1_IDX3    NORMAL     YES	       RANGE     LOCAL    INVISIBLE
T1_IDX4    BITMAP     YES	       RANGE     LOCAL    VISIBLE

SQL> ALTER SESSION SET OPTIMIZER_USE_INVISIBLE_INDEXES = TRUE;

Session altered.

SQL> SET AUTOTRACE TRACE EXPLAIN
SQL> 
SELECT *
FROM   t1
WHERE created_date = TO_DATE('01/07/2014', 'DD/MM/YYYY');SQL>   2    3  

Execution Plan
----------------------------------------------------------
Plan hash value: 1106166644

----------------------------------------------------------------------------------------------------------------------
| Id  | Operation				   | Name    | Rows  | Bytes | Cost (%CPU)| Time     | Pstart| Pstop |
----------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT			   |	     |	   1 |	  49 |	   1   (0)| 00:00:01 |	     |	     |
|   1 |  TABLE ACCESS BY GLOBAL INDEX ROWID BATCHED| T1      |	   1 |	  49 |	   1   (0)| 00:00:01 |	   1 |	   1 |
|*  2 |   INDEX RANGE SCAN			   | T1_IDX1 |	   1 |	     |	   1   (0)| 00:00:01 |	     |	     |
----------------------------------------------------------------------------------------------------------------------

SQL> SET AUTOTRACE OFF

我们可以看到优化器选择使用T1_IDX1索引,即使它是不可见的,而且在同一列列表上有一个可见的索引(T1_IDX4)。

参考文档

http://docs.oracle.com/database/121/NEWFT/chapter12101.htm#NEWFT002

http://docs.oracle.com/database/121/ADMIN/indexes.htm#GUID-05F3C3B0-DB80-489C-B749-01653FDE8E09

http://docs.oracle.com/database/121/ADMIN/indexes.htm#ADMIN13279 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Docker-Compose是一个用于定义和管理多个Docker容器的工具,可以方便地进行容器的创建、配置和启动。而Oracle 12c是一种商业数据库管理系统,具有高性能、可靠性和扩展性。 使用Docker-Compose来部署Oracle 12c可以带来一些好处。首先,Docker-Compose允许我们将多个容器打包到一个项目中,可以简化Oracle 12c的安装和配置过程。其次,Docker-Compose提供了一种快速部署和销毁容器的方式,可以极大地提高开发和测试的效率。 要使用Docker-Compose部署Oracle 12c,我们需要创建一个docker-compose.yml文件,并在其中指定所需的服务。在这个文件中,我们可以定义一个Oracle 12c容器,并设置所需的环境变量、映射的端口和数据卷等。此外,我们还可以设置网络设置,以便与其他容器进行通信。 在编写docker-compose.yml文件后,我们可以使用docker-compose命令来部署Oracle 12c容器。通过运行"docker-compose up"命令,Docker将会根据docker-compose.yml文件中的定义来创建和启动Oracle 12c容器。我们可以通过访问指定的端口来访问Oracle 12c数据库,并进行常规的数据库操作。 当我们不再需要Oracle 12c容器时,可以使用"docker-compose down"命令将其销毁。这将释放计算机资源并清理所有相关的容器和网络。 总而言之,使用Docker-Compose来部署Oracle 12c可以简化安装、配置和销毁过程,提高开发和测试效率。这种方式可以使我们更容易地创建和管理多个容器,并在需要时进行扩展。同时,使用Docker-Compose还可以提供一个一致的开发和测试环境,使得团队合作更加便捷和高效。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值