暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

TimesTen数据库中的数值类型优化

原创 漫步者 2023-01-04
308

在BSS3.0计费项目的实施过程中,我发现同样的数据存储在TimesTen(以下简称TT)中所占用的字节数比Oracle中占用的字节数要大,查阅资料后找到了原因,这是由于TT和Oracle的内部数据存储结构不同造成的,Oracle追求的是节省存储空间,TT追求的是提供最佳性能。如果我们在TT建表时选择的字段类型不当,也会造成TT内存严重浪费和表读写性能的下降。

因为计费系统和CRM系统中的数据存在密切相关性,所以在TT、MySQL、Oracle中的表模型会出现相同的属性字段,我们不仅需要关注这些相同属性字段的值域一致,还要关注不同数据库的数据类型差异,下面我们比较一下常见的整型数据类型在三种数据库中占用存储的不同表现。

在Oracle中,NUMBER类型是可变长的数据类型,数值NUMBER (p,s)占用的空间为 floor [(p+1)/2] + 1,如果是负数,还需要再增加一个字节,其最大精度p为38。Oracle为了兼容ANSI SQL,通常把INT、INTEGER、SMALLINT转换为NUMBER类型。如下图所示:

Oracle数据库中的产品实例ID,套餐实例ID等均为NUMBER(12),我们建一个测试表T2,插入不同值,通过dump函数查看记录所占用的字节数,发现1位数值占用2个字节,12位数值占用7个字节,16位的数值占用9个字节。


我们再来看看MySQL的表现:MySQL数值类型比较灵活丰富,整型支持TINYINT、SMALLINT、MEDIUMINT、INT、BIGIINT,这些数据类型占用字节如下表所示:

数据类型

占用字节

值域

TINYINT

1 byte

有符号的范围是-128到127,无符号的范围是0到255

SMALLINT

2 bytes

有符号的范围是-32768到32767,无符号的范围是0到65535

MEDIUMINT

3 bytes

有符号的范围是-8388608到8388607,无符号的范围是0到16777215

INT,INTEGER

4 bytes

有符号的范围是-2147483648到2147483647,无符号的范围是0到4294967295

BIGINT

8 bytes

有符号的范围是-9223372036854775808到 9223372036854775807,无符号的范围是0到18446744073709551615

DECIMAL(M,D),NUMERIC(M,D)

Varies

 

       需要注意的是,上表中MySQL的整型字段是支持无符号的。

除了DECIMAL类型是可变长以外,其它的都是定长类型,占用字节对应上表格第二列。DECIMAL类型和Oracle的NUMBER类型类似,但实现机制不同,MySQL使用二进制格式存储DECIMAL类型的值,它将每9位数字包装成4个字节,剩余数字个数不足9位时占用的字节数如下表所示。

剩余数字

占用字节

0

0

1–2

1

3–4

2

5–6

3

7-9

4

 

                  以DECIMAL(16,0)为例,小数部分占用0字节,整数部分分为9+7,9位占用4字节,剩余7位也占用4字节,共8字节;如果是DECIMAL(6),6是0倍个9,只需要查剩余6位数的占用字节,从上表可以看出来是3个字节,那么DECIMAL(6)就占用3个字节。而Oracle中NUMBER(14,0)就已经占用了8字节,所以MySQL更优一些。对应Oracle中的NUMBER[14~19]字段,显然,MySQL的数据类型BIGINT(8字节)更优;MySQL BIGINT支持有符号19位,无符号20位,如果使用MySQL的DECIMAL(19),那占用的就是13个字节,造成5个字节的浪费。

       另外值得一提的是,MySQL中的BIGINT(n),其中的n只是显示的占位符,它和精度一点关系都没有,好多人都容易误解这一点。

       我们最后再看TT中的数值类型。TT数值类型有:TT_TINYINT、TT_SMALLINT、TT_INTEGER、TT_BITINT和NUMBER,它们值域和占用字节情况如下表:

数据类型

占用字节

值域

TT_TINYINT

1 byte

无符号0到255

TT_SMALLINT

2 bytes

有符号-32768到32767

TT_INTEGER

4 bytes

有符号-2147483648到2147483647

TT_BITINT

8 bytes

有符号-9223372036854775808到9223372036854775807

NUMBER(p,s)

变长5-22字节

1.0×10-130到1.0×10126

我们在TT中建表,观察不同精度的NUMBER表现,从下图中我们发现TT中的NUMBER类型起步是5个字节,对应Oracle中的NUMBER(12)竟然用到了10个字节。以计费系统应用表中的主键字段NUMBER (16)为例,TT竟然需要12个字节。


       同样是Oracle的产品,差距怎么就这么大呢?

回顾TT的历史,我们就能发现TT原来是HP实验室出来的产品,后来被Oracle收购,我们日常拿TT当Oracle使用本身就存在很多问题,因为这二者本质上就是两个不同的产品。对于内存库来说,表数据和索引都是放在内存中的,表中不当的字段类型以及字段上面所创建的索引都会导致内存的浪费,同时也会影响数据的读写速度。在网络上存在大量吐槽TT过度占用内存的问题,其中一部分原因如前文所说——TT是为了追求性能最大化,有利用空间换时间的策略,另外一部分原因就是我们使用了不合适的字段类型。

       在《Oracle TimesTen In-Memory Database SQL Reference Guide7.0》第20页介绍TT数值类型的章节中,TT建议数值精度大于19的情况下使用NUMBER类型,数据表的读取性能更高;同时表明前文中提到的TT_开头的整型类型比NUMBER类型具有更好的紧凑性和性能。也就是说,在NUMBER类型小于19位长度的情况下,我们需要根据数值范围,把TT表字段类型分别对应到TT_TINYINT、TT_SMALLINT、TT_INTEGER和TT_BITINT这几种类型上。在我们计费账单表和余额表中通常存在非常多的NUMBER字段,如果把NUMBER (18)对应到TT_BITINT,各种FLAG、STATUS字段对应到TT_TINYINT后,对于亿级的内存表存储来说,能够减少的内存量是非常可观的。

       对于TT中的Date、Timestamp,TT_TIMESTAMP日期类型,它们和Oracle占用存储也有一定区别,限于篇幅,本文就不再展开论述,希望借此文抛砖引玉。我们需要更多地关注异构库的类型匹配问题,一般数据库厂家都会匹配自己的数据类型到ANSI SQL数据类型,我们可以根据不同厂家和ANSI的类型对标,就能找出两个不同数据库间的数据类型对应关系。

综上所述,我们在设计海量数据的数据库表模型时,需要特别关注字段的类型和值域问题,因为这不仅能减少数据的存储占用空间,而且也能大幅提升应用系统的性能。

最后修改时间:2024-03-06 11:46:18
「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论