龙盟编程博客 | 无障碍搜索 | 云盘搜索神器
快速搜索
主页 > 数据库类 > Oracle 技术 >

Oracle 11g新特性之模式管理(1)(2)

时间:2011-04-12 23:18来源:未知 作者:admin 点击:
分享到:
不可见的索引 您常常感到疑惑,索引是否真的有利于用户的查询?它可能有利于一个查询,但会影响 10 个其他查询。索引肯定会对 INSERT 语句造成负面影

不可见的索引

您常常感到疑惑,索引是否真的有利于用户的查询?它可能有利于一个查询,但会影响 10 个其他查询。索引肯定会对 INSERT 语句造成负面影响,也会执行潜在的删除和更新操作,这取决于 WHERE 条件是否在索引中包括该列。

一个相关的问题是,使用索引时,如果该索引被删除,会对查询性能造成什么影响?当然,您可以删除索引并查看对查询的影响,但说起来容易做起来难。索引实际上如何有助于查询?您必须重新定义索引,为此,需要进行重新创建。完全重新创建之后,就没有人能使用它了。重新创建索引也是一个昂贵的过程;它会占用许多有用的数据库资源。

您有办法创建一种对特定查询不可用同时又不会影响其他查询的索引吗?在 Oracle 数据库 11g 之前,不推荐使用 ALTER INDEX ...UNUSABLE,因为它会使表上的所有 DML 失败。但现在,您可以通过不可见的索引 精确使用该选项。简言之,您可以使索引对优化器“不可见”,这样就没有查询会使用它了。如果查询希望使用索引,则必须将其显式指定为提示。

下面是一个例子。假设有一个名为 RES 的表,并且您创建了如下所示的索引:

SQL> create index in_res_guest on res (guest_id);

分析完该表和索引后,如果您执行

SQL> select * from res where guest_id = 101;

将发现该索引正在使用:

Execution Plan
----------------------------------------------------------
Plan hash value: 1519600902
----------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
----------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 28 | 3 (0)| 00:00:01 || 1 | TABLE
 ACCESS BY INDEX ROWID| RES | 1 | 28 | 3 (0)| 00:00:01 ||* 2 |
INDEX RANGE SCAN | IN_RES_GUEST | 1 | | 1 (0)| 00:00:01 |
---------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
 2 - access("GUEST_ID"=101)

现在,使索引不可见:

SQL> alter index in_res_guest invisible; Index altered.

现在,将显示以下内容:

SQL> select * from res where guest_id = 101 2 / Execution Plan
----------------------------------------------------------
Plan hash value: 3824022422
----------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
----------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 28 | 140 (2)| 00:00:02 ||* 1 |
TABLE ACCESS FULL| RES | 1 | 28 | 140 (2)| 00:00:02 |
----------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("GUEST_ID"=101)

未使用索引。要使优化器再次使用索引,您必须在提示中显式命名索引:

SQL> select /**//*+ INDEX (res IN_RES_GUEST) */ res_id from
res where guest_id = 101;
-----------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-----------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 28 | 3 (0)| 00:00:01 || 1 |
TABLE ACCESS BY INDEX ROWID| RES | 1 | 28 | 3 (0)| 00:00:01 |
|* 2 | INDEX RANGE SCAN | IN_RES_GUEST | 1 | | 1 (0)| 00:00:01 |
-----------------------------------------------------------------

真快!优化器再次使用了索引。

或者,您可以设置会话级参数以使用不可见的索引:

SQL> alter session set optimizer_use_invisible_indexes = true;

如果您无法修改代码(如第三方应用程序中的代码),该特性将十分有用。您创建索引时,可以在末尾追加子句 INVISIBLE,将索引构建为对优化器不可见。您还可以使用字典视图 USER_INDEXES 查看索引的当前设置。

SQL> select visibility 2 from user_indexes 3 where index_name =
'IN_RES_GUEST';VISIBILITY---------INVISIBLE

注意,如果您重新构建该索引,则该索引将变为可见。您必须再次将其显式设为不可见。
那么,该索引到底对“什么”不可见?当然,它不会对用户不可见。它只是对优化器不可见。常规数据库操作(如插入、更新和删除)将继续更新索引。创建不可见索引时应注意这一点;由于该索引,您将不会再次查看性能,但同时您在 DML 操作期间可能会付出一些代价。

只读表

Robin 是 Acme 数据仓库系统的开发人员,他正在考虑一个典型问题。作为 ETL 流程的一部分,几个表的更新周期有所不同。在更新时,表会按业务规则对用户开放,即使用户不应修改它们。但是,取消用户对这些表的 DML 权限不是一个可选方法。

Robin 需要一个能够充当开关角色的功能,可以允许或不允许更新表。要实现这个听起来简单的操作,实际上相当困难。Robin 有哪些选择呢?

一个选择是,在表上创建一个触发器,以针对 INSERT、DELETE 和 UPDATE 引发异常。执行触发器会涉及上下文切换,这会影响性能。另一个选择是,创建一个虚拟专用数据库 (VPD) 策略,始终返回 false 字符串(如“1=2”)。如果表上的 VPD 策略使用该函数,它就会返回 FALSE,并且 DML 会失败。这可能比使用触发器具有更好的性能,但用户肯定不愿意使用,因为会看到“policy function returned error”之类的错误消息。

然而,在 Oracle 数据库 11g 中,您可以通过一个更好的方法来实现这个目标。您只需将表设为只读,如下所示:

SQL> alter table TRANS read only; Table altered.

现在,当用户尝试执行如下所示的 DML 时:

SQL> delete trans;

Oracle 数据库 11g 就会立即抛出错误:

delete trans *ERROR at line 1:ORA-12081: update operation not all
owed on table "SCOTT"."TRANS"

错误消息不会将操作反映到代码中,但会有目的地传递消息,而无需触发器或 VPD 策略的开销。

如果您希望表可更新,则需要将其设为读/写,如下所示:

SQL> alter table trans read write; Table altered.

现在,DML 就没有问题了:

SQL> update trans set amt = 1 where trans_id = 1; 1 row updated.

当表仅处于只读模式时,则不允许执行 DML;但您可以执行所有 DDL 操作(创建索引、维护分区等)。因此,这个特性的一个非常有用的应用就是表维护。您可以将表设为只读,执行必要的 DDL,然后再将其设为读/写。

要查看表的状态,请在数据字典视图 dba_tables 中查找 read_only 列。

SQL> select read_only from user_tables where table_name = 'TRANS'; REA---NO

结论:

如您所见,这些特性不仅大大简化了以前费力的命令,在某些情况下,还可以根据日常操作的执行开发全新的方式。

在我的职业生涯中,经历了 Oracle 数据库功能的许多更改,其中有一些标志性特性重新定义了业务的完成过程。这里描述的特性就属于这一类特性。

  1. Oracle 11gR1中的SecureFile
  2. Oracle 11g数据库重放教程
  3. 解析Oracle 11g闪回数据归档新功能
精彩图集

赞助商链接