ITPub博客

首页 > 数据库 > Oracle > [20201201]约束大写与查询.txt

[20201201]约束大写与查询.txt

原创 Oracle 作者:lfree 时间:2020-12-01 16:10:12 1 删除 编辑

[20201201]约束大写与查询.txt

--//开发在谓词条件中使用大写函数,我看了表中数据全部是大写。而查询条件两者情况都出现,看看是否加入约束,取消建立函数索引
--//的需求。

1.环境:
SCOTT@book> @ ver1
PORT_STRING                    VERSION        BANNER
------------------------------ -------------- --------------------------------------------------------------------------------
x86_64/Linux 2.4.xx            11.2.0.4.0     Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production

SCOTT@book> create table t1 as select rownum id,dbms_random.string('U',6) vc from dual connect by level<=1e5;
Table created.

SCOTT@book> select * from t1 where vc <> UPPER(vc);
no rows selected
--//全部是大写vc字段。

SCOTT@book> create index i_t1_vc on t1(vc);
Index created.

SCOTT@book> create index if_t1_vc on t1(upper(vc));
Index created.

alter table t1 add ( constraint ck_upper_vc check (vc = upper(vc)) enable validate);

2.测试:

SCOTT@book> select id from t1 where vc='A';
no rows selected

Plan hash value: 1263437441
----------------------------------------------------------------------------------------
| Id  | Operation                   | Name    | E-Rows |E-Bytes| Cost (%CPU)| E-Time   |
----------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |         |        |       |     2 (100)|          |
|   1 |  TABLE ACCESS BY INDEX ROWID| T1      |      1 |    12 |     2   (0)| 00:00:01 |
|*  2 |   INDEX RANGE SCAN          | I_T1_VC |      1 |       |     1   (0)| 00:00:01 |
----------------------------------------------------------------------------------------

SCOTT@book> select id from t1 where upper(vc)='A';
no rows selected

Plan hash value: 1591134070
-----------------------------------------------------------------------------------------
| Id  | Operation                   | Name     | E-Rows |E-Bytes| Cost (%CPU)| E-Time   |
-----------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |          |        |       |    67 (100)|          |
|   1 |  TABLE ACCESS BY INDEX ROWID| T1       |   1000 | 12000 |    67   (0)| 00:00:01 |
|*  2 |   INDEX RANGE SCAN          | IF_T1_VC |    400 |       |     1   (0)| 00:00:01 |
-----------------------------------------------------------------------------------------
--//可以发现分别使用各自的索引。

3.隐藏索引测试看看:
SCOTT@book> alter index if_t1_vc invisible;
Index altered.

SCOTT@book> select id from t1 where upper(vc)='A';
no rows selected

Plan hash value: 3617692013
---------------------------------------------------------------------------
| Id  | Operation         | Name | E-Rows |E-Bytes| Cost (%CPU)| E-Time   |
---------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      |        |       |    69 (100)|          |
|*  1 |  TABLE ACCESS FULL| T1   |   1000 | 12000 |    69   (2)| 00:00:01 |
---------------------------------------------------------------------------
Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------
   1 - SEL$1 / T1@SEL$1
Predicate Information (identified by operation id):
---------------------------------------------------
   1 - filter(UPPER("VC")='A')
--//很明显隐藏函数索引行不通,反过来测试看看。

SCOTT@book> alter index if_t1_vc visible;
Index altered.

SCOTT@book> alter index i_t1_vc invisible;
Index altered.
--//现在函数索引有效。

SCOTT@book> select id from t1 where vc='A';
no rows selected

SCOTT@book> @ dpc '' ''
PLAN_TABLE_OUTPUT
-------------------------------------
SQL_ID  b4twjdv2mqt2n, child number 0
-------------------------------------
select id from t1 where vc='A'
Plan hash value: 1591134070
-----------------------------------------------------------------------------------------
| Id  | Operation                   | Name     | E-Rows |E-Bytes| Cost (%CPU)| E-Time   |
-----------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |          |        |       |    67 (100)|          |
|*  1 |  TABLE ACCESS BY INDEX ROWID| T1       |      1 |    12 |    67   (0)| 00:00:01 |
|*  2 |   INDEX RANGE SCAN          | IF_T1_VC |    400 |       |     1   (0)| 00:00:01 |
-----------------------------------------------------------------------------------------
Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------
   1 - SEL$1 / T1@SEL$1
   2 - SEL$1 / T1@SEL$1
Predicate Information (identified by operation id):
---------------------------------------------------
   1 - filter("VC"='A')
   2 - access("T1"."SYS_NC00003$"='A')
--//在这样的情况下等值查询可以使用建立的函数索引。注意看Predicate Information部分,增加了filter("VC"='A')。

SCOTT@book> drop index i_t1_vc;
Index dropped.

--//再次验证,过程略。
4.总结:
--//这样可以建立一个函数索引,覆盖等值查询,不过不是我前面提到的取消函数索引建立,而是建立对应的函数索引。
--//建议开发在写代码时候好好想一下,谓词加入函数前自己写sql代码时心里要有一个弦,不然写一辈子的代码,做出来一堆垃圾,对不
--//起自己这份职业。
--//在收尾时在生产系统应用发现在11.2.0.3上无法实现。放弃,我只能建立2套索引,无语....

--//补充一点在建立函数索引后要单独分析表或者隐含列。不然E-ROWS不准.注意前面的E-Rows不准,可能在连接时可能出现不好的执行计划。
--//重新分析表后的测试:

SCOTT@book> select id from t1 where upper(vc)='A';
no rows selected

SCOTT@book> @ dpc '' ''
PLAN_TABLE_OUTPUT
-------------------------------------
SQL_ID  0gy85dby7p25q, child number 0
-------------------------------------
select id from t1 where upper(vc)='A'
Plan hash value: 1591134070
-----------------------------------------------------------------------------------------
| Id  | Operation                   | Name     | E-Rows |E-Bytes| Cost (%CPU)| E-Time   |
-----------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |          |        |       |     2 (100)|          |
|   1 |  TABLE ACCESS BY INDEX ROWID| T1       |      1 |    12 |     2   (0)| 00:00:01 |
|*  2 |   INDEX RANGE SCAN          | IF_T1_VC |      1 |       |     1   (0)| 00:00:01 |
-----------------------------------------------------------------------------------------
Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------
   1 - SEL$1 / T1@SEL$1
   2 - SEL$1 / T1@SEL$1
Predicate Information (identified by operation id):
---------------------------------------------------
   2 - access("T1"."SYS_NC00003$"='A')
--//现在E-rows=1.

来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/267265/viewspace-2738533/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论
熟悉oracle相关技术,擅长sql优化,rman备份与恢复,熟悉linux shell编程。

注册时间:2008-01-03

  • 博文量
    4006
  • 访问量
    7970751