假设我在Oracle 12c中有一个表格,其中包含以下列:
create table t1 (
a number (5,0),
b varchar (5,0)
d ...
e ...
);
然后我在两个具有相同值的列中插入100,000,000条记录 - 例如
20151 and '20152' ... (for a first record)
20152 and '20152' ... (for a second record)
20153 and '20153' ... (for a third record)
...
然后我在列'a'
上添加索引1,在列'b'.
上添加索引2
问题是 - 在列'a'
上执行列'b'
时查询的执行速度是否相同(例如join
查询基于列'a'
的其他表或基于任一列上的列'b'
或WHERE
子句?)
另外 - 在'varchar
'列上使用索引 - 使用比在'number'列上使用索引更多的CPU?
感谢。
答案 0 :(得分:1)
[TL; DR] 使用日期存储日期,存储数字的数字和存储字符串的字符串。
资源使用情况如何?
Oracle将NUMBER
数据类型存储为每2位1个字节。
Oracle将CHAR
数据类型存储为每个ASCII字符1个字节(UTF-8和其他编码可能需要更多扩展集中的字符),并将字符串用空格字符填充,以便字符串全部完全相同的长度。
Oracle将VARCHAR2
数据类型存储为每个ASCII字符1个字节加上字符串长度的小开销(1或2个字节)。
Oracle将DATE
数据类型存储为7 bytes(年份为2,月,日,时,分,秒各为1)。
根据your previous question,您似乎正在存储year
和quarter
,并假设您总是会有4位数年份和1位数季度:
NUMBER(5,0)
需要3个字节; CHAR(5 CHARACTER)
需要5个字节; VARCHAR2(5 CHARACTER)
需要6个字节;和DATE
需要7个字节。因此,只考虑记忆NUMBER(5,0)
将是最有效的。
一旦你开始对存储为数字/字符串的年/季度进行算术运算,你就会遇到性能问题:
例如,下一季度:
quarter
是NUMBER
数据类型,那么您可以使用:CASE WHEN MOD(quarter,10) = 4 THEN quarter + 7 ELSE quarter + 1 END
但是当您想要添加5个季度或开始减去季度时,这不会处理逻辑开始变得更加复杂。quarter
是CHAR
数据类型,那么您可以将其转换为数字或日期并使用其中任何一种方法(字符串操作不太可能具有高效性)。quarter
是DATE
,那么您只需要使用ADD_MONTHS( quarter, 3 )
。 DATE
方法是自我记录的并且已经存在,而NUMBER
方法只是成为QUARTER
数据类型近似的自定义函数,并且一旦实现所有比较您需要的操作函数将有效地将DATE
数据类型重写为四分之一的UDT,并且这些函数的性能将不如优化的日期函数。
不要使用不合适的数据类型 - 只将日期存储为日期;数字作为数字;和字符串作为字符串。