您的位置:首页 > 数据库 > Oracle

Oracle char 与 varchar2的区别

2011-02-19 17:21 169 查看
char和Varchar2在Oracle的内部存储格式都一样都是数据长度length+实际数据data,其中数据长度length用1-3个字节表示,length<255字节的使用1个字节,length>255用3个字节表示。
Thomas Kyte的建议是忘记有char类型的存在,在一切需要字符的地方都是用varchar2格式。
“不过,如果混合使用并匹配 VARCHAR2 和 CHAR ,你就会不断地遭遇这个问题。不仅如此,开发人员 现
在还必须在应用中考虑字段宽度。如果开发人员喜欢使用 RPAD() 技巧将绑定变量转换为某种能与 CHAR 字
段比较的类型(当然,与截断( TRIM )数据库列相比,填充绑定变量的做法更好一些,因为对列应用函数
TRIM 很容易导致无法使用该列上现有的索引),可能必须考虑到经过一段时间后列长度的变化。如果字段
的大小有变化,应用就会受到影响,因为它必须修改字段宽度。
正是由于以下这些原因:定宽的存储空间可能导致表和相关索引比平常大出许多,还伴随着绑定变 量
问题,所以无论什么场合我都会避免使用 CHAR 类型。即便是对单字符的字段,我也想不出有什么必要使 用
CHAR 类型,因为在这种情况下,这两种类型确实没有显著差异。 VARCHAR2(1) 和 CHAR(1) 从任何方面来讲 都
完全相同。此时,使用 CHAR 类型并没有什么有说服力的理由,为了避免混淆,所以我 “ 一律排斥 “ ,即 使
是 CHAR(1) 字段(即单字符字段)也不建议使用 CHAR 类型。”
下面链接是AskTom中关于char和Varchar2的区别的讨论:
http://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:123212348063
 
经常有人说,char的性能比varchar的性能好,做下试验测试:
create table test (key number , char_str char(50),varchar_str varchar2(50));
insert into test select rownum,object_id,object_id from dba_objects;
insert into test select rownum+50530 ,object_id+50530,object_id+50530 from dba_objects;
insert into test select rownum+150530 ,object_id+150530,object_id+150530 from dba_objects;
commit;
select count(*) from test;
COUNT(*)
---------
   151560
set autotr on exp
select * from test where char_str='asjdfa';
no rows selected
Execution Plan
----------------------------------------------------------
Plan hash value: 1357081020
--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      |    16 |  1472 |   328   (4)| 00:00:04 |
|*  1 |  TABLE ACCESS FULL| TEST |    16 |  1472 |   328   (4)| 00:00:04 |
--------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   1 - filter("CHAR_STR"='asjdfa')
Note
-----
   - dynamic sampling used for this statement
select * from test where varchar_str='asjdfa';
no rows selected
Execution Plan
----------------------------------------------------------
Plan hash value: 1357081020
--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      |    16 |  1472 |   324   (3)| 00:00:04 |
|*  1 |  TABLE ACCESS FULL| TEST |    16 |  1472 |   324   (3)| 00:00:04 |
--------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   1 - filter("VARCHAR_STR"='asjdfa')
Note
-----
   - dynamic sampling used for this statement
结论:同一个条件varchar2和char的性能基本一样;
在char_str和varchar_str上分别建索引后的查看查询效率;
create index char_idx on test(char_str);
create index varchar_idx on test(varchar_str);
select * from test where char_str='20';
       KEY CHAR_STR                                                                                     VARCHA
---------- ---------------------------------------------------------------------------------------------------
--------------------------------------------------------------
         1 20                                                                                               20
Execution Plan
----------------------------------------------------------
Plan hash value: 4119847653
----------------------------------------------------------------------------------------
| Id  | Operation                   | Name     | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |          |     1 |    92 |     4   (0)| 00:00:01 |
|   1 |  TABLE ACCESS BY INDEX ROWID| TEST     |     1 |    92 |     4   (0)| 00:00:01 |
|*  2 |   INDEX RANGE SCAN          | CHAR_IDX |     1 |       |     3   (0)| 00:00:01 |
----------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   2 - access("CHAR_STR"='20')
Note
-----
   - dynamic sampling used for this statement
select * from test where varchar_str='20';
       KEY CHAR_STR                                                                                     VARCHAR_STR
---------- ---------------------------------------------------------------------------------------------------- -------------
--------------------------------------------------------------
         1 20                                                                                               20
Execution Plan
----------------------------------------------------------
Plan hash value: 2912297006
-------------------------------------------------------------------------------------------
| Id  | Operation                   | Name        | Rows  | Bytes | Cost (%CPU)| Time     |
-------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |             |     1 |    92 |     2   (0)| 00:00:01 |
|   1 |  TABLE ACCESS BY INDEX ROWID| TEST        |     1 |    92 |     2   (0)| 00:00:01 |
|*  2 |   INDEX RANGE SCAN          | VARCHAR_IDX |     1 |       |     1   (0)| 00:00:01 |
-------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   2 - access("VARCHAR_STR"='20')
Note
-----
   - dynamic sampling used for this statement
结论:在对于字段有索引的情况下,其select效率是一样的,甚至varchar2还表现的效率高点。
再来查看下同样的数据char和varchar2空间利用的比较;
SQL> select sum(bytes/1024/1024) as char_idx_used_mb  from user_segments where segment_name='CHAR_IDX';
CHAR_IDX_USED_MB
----------------
              11
SQL> select sum(bytes/1024/1024) as char_idx_used_mb  from user_segments where segment_name='VARCHAR_IDX';
CHAR_IDX_USED_MB
----------------
               3
同样的数据char 索引比varchar索引的使用空间要大将近3倍,也就说同样的数据在表中char列的存储空间比varchar2的存储空间大将近3倍左右;当然这个比例跟存入表中char和varchar2列中的数据有关,如果存入char列中数据接近其定义的长度,那么char与varchar2的存储空间将差不多。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息