[20151119]nvarchar2类型.txt

[20151119]nvarchar2类型.txt

-- 前几天帮别人看awr报表,连接如下:http://www.itpub.net/thread-1942785-1-1.html
-- 最终确定是使用navrchar2存在隐式转换,实际上如果应用没有国际化需求,不要使用这个类型,通过一些例子来说明问题。

1.环境:
SCOTT@book> create table t ( id number,c1 varchar2(20),c2 nvarchar2(20));
Table created.

SCOTT@book> insert into t values (1,'aaaa','bbbb');
1 row created.

SCOTT@book> insert into t values (2,'文化','文化');
1 row created.

SCOTT@book> commit ;
Commit complete.

2.先来看看内部格式:
SCOTT@book> select id,dump(c1,16) c30 ,dump(c2,16) c40 from t ;

SCOTT@book> select id,dump(c1,16) c30 ,dump(c2,16) c40 from t ;
        ID C30                            C40
---------- ------------------------------ ----------------------------------------
         1 Typ=1 Len=4: 61,61,61,61       Typ=1 Len=8: 0,62,0,62,0,62,0,62
         2 Typ=1 Len=4: ce,c4,bb,af       Typ=1 Len=4: 65,87,53,16

--可以发现保存4个英文字符,varchar2类型c1仅仅占用4个字节,而nvarchar2占用8个字节。
--而保存汉字"文化",注意看nvarchar2保存的是"65,87,53,16"(16进制)。如果不告诉你类型很难猜到类型。
-- 0x65 对应的是 'e'.

SCOTT@book> select dump('e',16) from dual ;
DUMP('E',16)
----------------
Typ=96 Len=1: 65

SCOTT@book> select rowid,t.*  from t ;
ROWID                      ID C1                   C2
------------------ ---------- -------------------- ----
AAAVuQAAEAAAAIPAAB          1 aaaa                 bbbb
AAAVuQAAEAAAAIPAAC          2 文化                 文化

SCOTT@book> @ &r/rowid AAAVuQAAEAAAAIPAAB
    OBJECT       FILE      BLOCK        ROW DBA                  TEXT
---------- ---------- ---------- ---------- -------------------- ----------------------------------------
     88976          4        527          1 4,527                alter system dump datafile 4 block 527 ;

--补充bbed的观察:
BBED> p *kdbr[1]
rowdata[16]
-----------
ub1 rowdata[16]                             @8157     0x2c

BBED> x /rncc
rowdata[16]                                 @8157
-----------
flag@8157: 0x2c (KDRHFL, KDRHFF, KDRHFH)
lock@8158: 0x00
cols@8159:    3

col    0[2] @8160: 1
col    1[4] @8163: aaaa
col    2[8] @8168: .b.b.b.b

BBED> p *kdbr[2]
rowdata[0]
----------
ub1 rowdata[0]                              @8141     0x2c

BBED> x /rncc
rowdata[0]                                  @8141
----------
flag@8141: 0x2c (KDRHFL, KDRHFF, KDRHFH)
lock@8142: 0x01
cols@8143:    3

col    0[2] @8144: 2
col    1[4] @8147: ....
col    2[4] @8152: e.S.

3.再来看看语句的执行计划:

SCOTT@book> select *  from t where c1=c2;
        ID C1                   C2
---------- -------------------- -------
         2 文化                 文化

SCOTT@book> @ &r/dpcz ''
PLAN_TABLE_OUTPUT
-------------------------------------
SQL_ID  1d5vntz02hc3g, child number 0
-------------------------------------
select *  from t where c1=c2
Plan hash value: 1601196873
---------------------------------------------------------------------------
| Id  | Operation         | Name | E-Rows |E-Bytes| Cost (%CPU)| E-Time   |
---------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      |        |       |     3 (100)|          |
|*  1 |  TABLE ACCESS FULL| T    |      1 |    15 |     3   (0)| 00:00:01 |
---------------------------------------------------------------------------
Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------
   1 - SEL$1 / T@SEL$1
Predicate Information (identified by operation id):
---------------------------------------------------
   1 - filter("C2"=SYS_OP_C2C("C1"))

--注意看过滤条件("C2"=SYS_OP_C2C("C1"))。
--如果你使用常量还没有什么问题,虽然都是字符类型,但是低级向高级转换,例子如下:

SCOTT@book> select *  from t where c2='文化';
        ID C1                   C2
---------- -------------------- -----
         2 文化                 文化

SCOTT@book> @ &r/dpcz ''
PLAN_TABLE_OUTPUT
-------------------------------------
SQL_ID  8ty74dq99bn17, child number 0
-------------------------------------
select *  from t where c2='文化'
Plan hash value: 1601196873
---------------------------------------------------------------------------
| Id  | Operation         | Name | E-Rows |E-Bytes| Cost (%CPU)| E-Time   |
---------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      |        |       |     3 (100)|          |
|*  1 |  TABLE ACCESS FULL| T    |      1 |    15 |     3   (0)| 00:00:01 |
---------------------------------------------------------------------------
Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------
   1 - SEL$1 / T@SEL$1
Predicate Information (identified by operation id):
---------------------------------------------------
   1 - filter("C2"=U'\6587\5316')

--可以发现过滤条件会转换为("C2"=U'\6587\5316')。

4.最可怕的是混用,这样问题更大:
--加上这个表的字段c1在另外一些表也是nvarchar2类型:

SCOTT@book> select *  from t where c1=U'文化';
        ID C1                   C2
---------- -------------------- ------
         2 文化                 文化

SCOTT@book> @ &r/dpcz ''
PLAN_TABLE_OUTPUT
-------------------------------------
SQL_ID  gmcpuhpasg78a, child number 0
-------------------------------------
select *  from t where c1=U'文化'

Plan hash value: 1601196873

---------------------------------------------------------------------------
| Id  | Operation         | Name | E-Rows |E-Bytes| Cost (%CPU)| E-Time   |
---------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      |        |       |     3 (100)|          |
|*  1 |  TABLE ACCESS FULL| T    |      1 |    15 |     3   (0)| 00:00:01 |
---------------------------------------------------------------------------
Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------
   1 - SEL$1 / T@SEL$1
Predicate Information (identified by operation id):
---------------------------------------------------
   1 - filter(SYS_OP_C2C("C1")=U'\6587\5316')

--这样要避开全部扫描,要建立SYS_OP_C2C("C1")的函数索引。

5.总结:
--如果你的应用要求使用nvarcha2(20),最好全部都是这个类型,或者相关这些字段都是这个类型。如果没有这种需求不要乱用这样的数据
--类型,实际上我已经遇到过这种类型,给出的解答让我苦笑不得,我们要考虑更长远的需求,实际上他们的程序就是一堆垃圾,你要使
--用这种类型,必须了解这种数据类型的利弊。

时间: 2024-10-17 09:20:50

[20151119]nvarchar2类型.txt的相关文章

[20171203]关于raw类型.txt

[20171203]关于raw类型.txt --//从来没有关注raw类型,昨天看https://blog.dbi-services.com/doag-2017-avg_row_len-with-virtual-columns/ --//我第一次接触一个应用使用sys_guid()函数生成键值,不过对方使用-分割,36位字符串长度.一个表有6个这样的字段.昏.. --//还真的没有反过来想利用raw类型可以减少磁盘空间占用. 1.环境: SCOTT@test01p> @ ver1 PORT_ST

[20150503]关于oracle的number类型.txt

[20150503]关于oracle的number类型.txt --节前的事情,别人建表使用number类型,本来想定义成number(10,2),结果少输入0,变成number(1,2). --在我的记忆里,好像前面的数值应该大于后面的精度的,没想到这样竟然可以通过,自己感到很奇怪! --测试下来,才知道自己oracle基本的东西都不是很清楚. 1.首先提到我以前写的一篇blog: [20140823]在sqlplus使用copy注意.txt http://blog.itpub.net/267

[20160828]number类型.txt

[20160828]number类型.txt --昨天看了一个链接http://www.cnblogs.com/kerrycode/p/4427352.html,感觉有点不对,上班测试看看. 1.环境: SCOTT@book> @ &r/ver1 PORT_STRING                    VERSION        BANNER ------------------------------ -------------- -------------------------

[20161123]oracle数据块类型.txt

[20161123]oracle数据块类型.txt --oracle 数据块有许多类型,自己平时很少关注与记忆,自己做一个归纳总结: 1.环境: SCOTT@book> @ &r/ver1 PORT_STRING                    VERSION        BANNER ------------------------------ -------------- ------------------------------------------------------

[20170114]12c varchar2类型直方图.txt

[20170114]12c varchar2类型直方图.txt --我曾经提到慎用nvarchar2数据类型,链接:http://blog.itpub.net/267265/viewspace-2120925/ --我那里提到数据类型nvarchar2类型,因为1个字符占用2个字节,这样如果前面16个字符重复很多,直方图的建立就是鸡肋, --毫无用处(因为分析仅仅对前面32个字节有效),12c 直方图支持更多类型: 高度直方图,频率直方图.混和类型(HYBRID). --看看12c关于直方图方面

[20170402]函数索引standard_hash.txt

[20170402]函数索引standard_hash.txt --//这几天放假,在家里看书<<Apress.Expert.Oracle.Indexing.and.Access.Paths.Maximum.Performance.for.Your.Database.2nd.Edition.148421983X.pdf>> --//这本书比较合适初学者,我以前看过第一版,所以这个版本看的很快. --//里面提到函数standard_hash,可以用来满足一般的查询,做一个记录. 1

Oracle数据库入门之函数/类型

Oracle主要数据类型 概述:各种数据库所支持的数据类型大同小异,与标准SQL语言中的数据类型可能略有出入 类型:varchar2:可以在声明字段时设置它的长度上限.而且使用它之后,就不必再考虑空格的存在 若插入的字符串的长度低于长度上限,系统就会自动将其缩减为字符串的真实长度 number(m,n):既可以用来表示整型,也可以表示浮点型.但m不可以超过38.如果n为0或者省略n,就代表它是整数 date:用来存放日期和时间 blob:通常是在应用程序中使用到它,而不是在数据库中利用SQL指令

《卸甲笔记》-PostgreSQL和Oracle的数据类型的对比系列一:字符类型

PostgreSQL是世界上功能最强大的开源数据库,在国内得到了越来越多机构和开发者的青睐和应用.随着PostgreSQL的应用越来越广泛,Oracle向PostgreSQL数据库的数据迁移需求也越来越多.数据库之间数据迁移的时候,首先遇到的,并且也是最重要的,就是数据类型之间的转换.下面根据自己的理解和测试,写了一些数据类型之间的差异以及迁移时的注意事项的文章,不足之处,尚请多多指教. 字符类型 大家知道,Oracle有四种字符类型,分别是char,varchar2,nchar,nvarcha

Oralce中VARCHAR2()与NVARCHAR2()的区别介绍_oracle

一.先来看看Oralce中VARCHAR2()和NVARCHAR2()的官方定义 官方文档定义如下: VARCHAR2(size [BYTE | CHAR]) Variable-length character string having maximum length size bytes or characters. Maximum size is 4000 bytes or characters, and minimum is 1 byte or 1 character. You must