对于那些有兴趣在一些指标,这里有一系列的SQL语句来测试一个字符列的查询(VARCHAR2(1))和1位柱(NUMBER(1))。
测试设置 - 使用字符状态列和数字状态列创建100,000,000行表。运行一个简单的查询来使用字符状态过滤器对行进行计数,并将其时间与使用数字状态运行类似查询的时间进行比较。
执行摘要 - 差别不明显。
SQL> create table some_100_rows
2 as
3 select rownum as rnum
4 from dual
5 connect by level <= 100;
Table created.
SQL> create table some_1000000_rows
2 as
3 select ROWNUM as id
4 , cast(case when mod(rownum, 2) = 0 then 'S' else 'C' end as varchar2(1)) as varchar_status
5 , cast(case when mod(rownum, 2) = 0 then 1 else 2 end as number(1)) as num_status
6 from dual
7 connect by level <= 1000000
8 ;
Table created.
Elapsed: 00:00:01.46
(我保持数据和分布简单,所以字符检索和搜索数在做同样的事情,时间差异应该是由于单独的数据类型。)
SQL> create table test_varchar_vs_number -- a table of 100,000,000 rows
2 as
3 select t1.*
4 from some_1000000_rows t1
5 cross join
6 some_100_rows t2
7 ;
Table created.
Elapsed: 00:00:37.96
SQL> select count(*)
2 from test_varchar_vs_number
3 ;
COUNT(*)
----------
100000000
Elapsed: 00:00:10.54
请注意,只计算表格需要大约10秒。
这里的内容是什么样子:
SQL> select *
2 from test_varchar_vs_number
3 where rownum < 11;
ID VARCHAR_STATUS NUM_STATUS
---------- -------------- ----------
1 C 2
2 S 1
3 C 2
4 S 1
5 C 2
6 S 1
7 C 2
8 S 1
9 C 2
10 S 1
10 rows selected.
Elapsed: 00:00:00.04
运行选择带有“S”在VARCHAR_STATUS列数行数。重复几次以获得稳定的指标。
SQL> select count(*)
2 from test_varchar_vs_number
3 where varchar_status = 'S'
4 ;
COUNT(*)
----------
50000000
**Elapsed: 00:00:11.82**
SQL> select count(*)
2 from test_varchar_vs_number
3 where varchar_status = 'S'
4 ;
COUNT(*)
----------
50000000
**Elapsed: 00:00:11.05**
SQL> select count(*)
2 from test_varchar_vs_number
3 where varchar_status = 'S'
4 ;
COUNT(*)
----------
50000000
**Elapsed: 00:00:11.37**
因此只需要超过11秒来计算50,000,000个“S”行。
现在尝试与行同样的事情用一个1在NUMBER_STATUS列:
SQL> select count(*)
2 from test_varchar_vs_number
3 where num_status = 1;
COUNT(*)
----------
50000000
**Elapsed: 00:00:11.04**
SQL> select count(*)
2 from test_varchar_vs_number
3 where num_status = 1;
COUNT(*)
----------
50000000
**Elapsed: 00:00:10.79**
SQL> select count(*)
2 from test_varchar_vs_number
3 where num_status = 1;
COUNT(*)
----------
50000000
**Elapsed: 00:00:10.59**
所以,不同的是可以忽略不计。 (Min chacter搜索时间:11.05s与最小搜索时间10.59s。)
编辑: 对于那些对低级别细节感兴趣的人,这里是来自通过tkprof的10046踪迹的统计。这是从上面单独运行,所以不要指望时间完全匹配。 (请记住,查询的所有3次运行的总时间。)
select count(*)
from test_varchar_vs_number
where num_status = 1
call count cpu elapsed disk query current rows
------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 3 0.00 0.00 0 0 0 0
Execute 3 0.00 0.00 0 0 0 0
Fetch 6 11.85 34.30 621984 622005 0 3
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 12 11.85 34.30 621984 622005 0 3
Misses in library cache during parse: 1
Optimizer mode: ALL_ROWS
Parsing user id: 110
Number of plan statistics captured: 3
Rows (1st) Rows (avg) Rows (max) Row Source Operation
---------- ---------- ---------- ---------------------------------------------------
1 1 1 SORT AGGREGATE (cr=207335 pr=207328 pw=0 time=11434679 us)
50000000 50000000 50000000 TABLE ACCESS FULL TEST_VARCHAR_VS_NUMBER (cr=207335 pr=207328 pw=0 time=10113986 us cost=56992 size=150000000 card=50000000)
Elapsed times include waiting on following events:
Event waited on Times Max. Wait Total Waited
---------------------------------------- Waited ---------- ------------
SQL*Net message to client 6 0.00 0.00
reliable message 1 0.00 0.00
enq: KO - fast object checkpoint 1 0.13 0.13
direct path read 4835 0.29 22.04
SQL*Net message from client 6 0.01 0.04
********************************************************************************
select count(*)
from test_varchar_vs_number
where varchar_status = 'S'
call count cpu elapsed disk query current rows
------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 3 0.00 0.00 0 0 0 0
Execute 3 0.00 0.00 0 0 0 0
Fetch 6 11.20 33.43 621984 622005 0 3
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 12 11.20 33.43 621984 622005 0 3
Misses in library cache during parse: 1
Optimizer mode: ALL_ROWS
Parsing user id: 110
Number of plan statistics captured: 3
Rows (1st) Rows (avg) Rows (max) Row Source Operation
---------- ---------- ---------- ---------------------------------------------------
1 1 1 SORT AGGREGATE (cr=207335 pr=207328 pw=0 time=11146155 us)
50000000 50000000 50000000 TABLE ACCESS FULL TEST_VARCHAR_VS_NUMBER (cr=207335 pr=207328 pw=0 time=9700296 us cost=56940 size=100000000 card=50000000)
Elapsed times include waiting on following events:
Event waited on Times Max. Wait Total Waited
---------------------------------------- Waited ---------- ------------
SQL*Net message to client 6 0.00 0.00
reliable message 1 0.00 0.00
enq: KO - fast object checkpoint 1 0.21 0.21
direct path read 4873 0.25 22.12
SQL*Net message from client 6 0.03 0.05
********************************************************************************
您将一次检索多少条记录并检查/比较它们的状态? 1千,10万,100万,1亿? – krokodilko
不知道,可能超过这个 – Ash
我的建议是一个简短的varchar2列,存储一个固定长度的alpha代码,另一个两列表将代码关联到描述性名称。对代码进行一些真正的思考,以提出符合当前需求的标准,但也可以在未来将其添加到角落的情况下进行添加。这实际上并不特定于任何数据库产品。这是基本的数据设计。 – EdStevens