【IT168 专稿】Altibase是由韩国公司开发的一款内存数据库产品,目前由天津南大通用在国内负责市场推广工作。
为了高效管理大容量数据库,Altibase被设计成高效使用每一层内存。在数据库系统软件中,内存分配( malloc )和复制( memset )大大的影响了系统的性能。Altibase内存管理模块的设计和实现机制是使用自己的内存池管理内存。Altibase的存储管理层(Storage Management Layer)管理内存中优化过的数据页,通过最大化各数据页之间的关系高效的存储和管理数据库。Altibase的查询处理层(Query Processing Layer) 在处理查询时高效管理内存空间,尽量减少由于不必要的内存分配和释放导致的性能下降 。
作为大容量数据库高效管理的方案,Altibase在一个DBMS中提供内存和磁盘存储区。同内存一样,基于磁盘的存储支持DRDBMS的LRU算法的缓冲池和物理磁盘存储管理。用户将希望的数据加载到缓冲池,与高性能内存存储区的数据最小化性能最低。
Altibase可以将数据库空间定位在内存的共享内存中,也可以定位在进程本地内存中。如果将数据库空间定位在共享内存中,在系统正常的情况下Altibase的重启时间非常短。因为以前数据库的状态仍然安全的保存在共享内存中,Altibase服务器可以使用现有的数据库空间,而不需要将磁盘上的备份数据库重新加载到内存中的数据库空间。
Altibase在内存中的数据空间分成不变的和临时的两部分空间。前者存储现有的表和元信息的数据,其内容反映到磁盘中备份数据库。而后者放置执行查询产生的索引数据和临时表。临时空间不反映到磁盘上的备份数据库,当Altibase服务器结束服务时,这个空间就会消失。
因为Altibase备份数据库不存储索引数据,所以索引数据是存在临时空间中间进行管理的。Altibase在数据库运行初期使用数据库目录中的索引信息创建索引。由于不在备份数据库中存储索引信息,Altibase不需要记录更新的日志,可以提高数据库的性能。
由于连续的插入数据造成贮存中的数据库的不变空间不足的情况下,Altibase按固定大小自动扩展空间。当然,扩展后的数据库空间保证反映到备份数据库的数据的稳定性。
安装配置
安装Altibase数据库,在Altibase网站注册可以下载有试用版本。下载到试用版本包以后,对压缩包进行解压缩:
解压缩后得到:
直接运行这个文件即可进行安装。
安装完成后设置Altibase的环境变量:
将以下几行加入到用户的profile中去:
export PATH=$ ALTIBASE_HOME/bin:$PATH
export LD_LIBRARY_PATH=$ ALTIBASE_HOME/lib:$LD_LIBRARY_PATH
在创建Altibase数据库实例前,可预先配置操作系统共享内存区的大小:
Cd /etc/rc.d/rc.local 目录,加上下面的语句;
echo 512 32000 512 512 > /proc/sys/kernel/sem
添加完后,重起系统。
创建和启动Altibase数据库:
执行如下命令:
$server create
创建Altibase数据库成功后显示下图信息:
启动Altibase数据库服务成功后显示下图信息:
${PageNumber}Benchmark测试
·测试环境
本次测试使用的软硬件环境如下:
硬件配置:Intel(R) Core(TM) i7 CPU 860 @ 2.80GHz,4核8线程, 内存8GB。
操作系统: Redhat Enterprise Linux 6.0 X64。
·测试假定
本次测试为充分展示内存数据库的性能,使用Altibase的内存方式运行,并使用Altibase的CLI接口来完成测试。
·数据结构
插入测试
1. 单线程
首先进行单线程的插入测试,向数据库中插入10000000条记录,性能如下:
线程ID | 记录数 | 耗时(毫秒) |
1 | 10000000 | 232413 |
每条记录所花费的时间(微秒) | 23.2413 | |
每秒吞吐率(object/s) | 43026.85306 |
单线程插入10000000条记录的耗时为232秒,每条记录的花费时间为23微秒,每秒处理的记录数为4.3万。
2. 四线程
之后我们增加线程数为4.
四个线程同时插入10000000条记录,性能如下:
线程ID | 记录数 | 耗时(毫秒) |
1 | 2500000 | 96830 |
2 | 2500000 | 96914 |
3 | 2500000 | 97234 |
4 | 2500000 | 97867 |
插入10000000条记录所花费的总时间(秒) | 97211.25 | |
每条记录所花费的时间(微秒) | 9.721125 | |
每秒吞吐率(object/s) | 102868.7523 |
四个线程插入10000000条记录的总耗时为97.2秒,平均每条记录耗时9.7微秒,每秒处理10.3万条数据。
3. 八线程
最后将线程数增加到八个线程,向数据库中添加10000000条记录,每个线程的性能和总体性能如下:
线程ID | 记录数 | 耗时(毫秒) |
1 | 1250000 | 94849 |
2 | 1250000 | 97658 |
3 | 1250000 | 97861 |
4 | 1250000 | 97847 |
5 | 1250000 | 98002 |
6 | 1250000 | 98333 |
7 | 1250000 | 98461 |
8 | 1250000 | 98810 |
插入10000000条记录所花费的总时间(秒) | 97.727625 | |
每条记录所花费的时间(微秒) | 9.7727625 | |
每秒吞吐率(object/s) | 102325.2125 |
可以看到8个并发写入10000000条记录所花费的时间大概为97.7秒,平均每秒可以添加10万条记录。
4. 总结
插入操作的总体吞吐率:
可以看到,插入操作的性能,四个线程的吞吐率最大。
${PageNumber}更新测试
1. 单线程
首先进行单线程的更新测试,在数据库中进行10000000次更新,每次更新一条记录的所有字段,性能如下:
线程ID | 记录数 | 耗时(毫秒) |
1 | 10000000 | 266660 |
每条记录所花费的时间(微秒) | 26.666 | |
每秒吞吐率(object/s) | 37500.9375 |
单线程更新10000000条记录的耗时为266秒,每条记录的更新花费时间为26.6微秒,每秒处理的记录数为3.75万。
2. 四线程
之后我们增加线程数为4.
四个线程同时更新10000000条记录,性能如下:
线程ID | 记录数 | 耗时(毫秒) |
1 | 2500000 | 116229 |
2 | 2500000 | 116907 |
3 | 2500000 | 117151 |
4 | 2500000 | 117802 |
插入10000000条记录所花费的总时间(秒) | 117022.25 | |
每条记录所花费的时间(微秒) | 11.702225 | |
每秒吞吐率(object/s) | 85453.8346 |
四个线程更新10000000条记录的总耗时为117秒,平均每条记录耗时11.7微秒,每秒处理8.5万条数据。
3. 八线程
更新测试是通过八个线程,同时更新数据库中记录,共10000000次操作,每个线程的性能和总体性能如下:
线程ID | 记录数 | 耗时(毫秒) |
1 | 1250000 | 121126 |
2 | 1250000 | 121656 |
3 | 1250000 | 125772 |
4 | 1250000 | 125488 |
5 | 1250000 | 126340 |
6 | 1250000 | 126902 |
7 | 1250000 | 126493 |
8 | 1250000 | 127313 |
更新10000000条记录的耗时(秒) | 125.13625 | |
更新每条记录所的耗时(微秒) | 12.513625 | |
每秒吞吐率(object/s) | 79912.8949 |
可以看到8个并发同时更新10000000条记录所花费的时间大概为125秒,平均每秒可以更新8万条记录。此处的更新为涉及到了每条记录的每个字段。
4. 总结
更新操作的总体吞吐率:
可以看到,更新操作的性能,同样也是四个线程并发操作时,吞吐率最大。
${PageNumber}查询测试
1. 单线程
首先进行单线程的查询测试,在数据库中进行10000000次查找,性能如下:
线程ID | 记录数 | 耗时(毫秒) |
1 | 10000000 | 64418 |
每条记录所花费的时间(微秒) | 6.4418 | |
每秒吞吐率(object/s) | 155236.1141 |
单线程进行10000000次查询的耗时为64秒,每次查询花费时间为6.4微秒,每秒处理的操作数为15.5万。
2. 四线程
之后我们增加线程数为4.
四个线程进行10000000次查找操作,性能如下:
线程ID | 记录数 | 耗时(毫秒) |
1 | 2500000 | 20650 |
2 | 2500000 | 21420 |
3 | 2500000 | 21658 |
4 | 2500000 | 21340 |
插入10000000条记录所花费的总时间(秒) | 21.267 | |
每条记录所花费的时间(微秒) | 2.1267 | |
每秒吞吐率(object/s) | 470212.0656 |
四个线程进行10000000次查找操作的总耗时为21秒,平均每条记录耗时2.1微秒,每秒处理47万次查询操作。
3. 八线程
查询测试是通过八个线程,同时查询数据库中记录,共10000000次查询,每个线程的性能和总体性能如下:
线程ID | 记录数 | 耗时(毫秒) |
1250000 | 19127 | |
1250000 | 19574 | |
1250000 | 18892 | |
1250000 | 19567 | |
1250000 | 19258 | |
1250000 | 19111 | |
1250000 | 19559 | |
8 | 1250000 | 19794 |
查询10000000次的耗时(秒) | 19.36025 | |
每次查询的耗时(微秒) | 1.936025 | |
每秒吞吐率(object/s) | 516522.2557 |
可以看到8个并发同时查询10000000条记录所花费的时间大概为19秒,平均每秒可以进行51.6万次查询。
4. 总结
查询操作的总体吞吐率:
可以看到,查询操作的性能,是8个线程并发操作时,吞吐率最大。
${PageNumber}1:1读写测试
1. 四线程
首先进行四线程的读写测试,其中2个线程做更新操作,另外两个线程做查询操作,持续运行10秒钟,每个线程的性能和总体性能如下:
线程ID | 操作 | 操作次数 |
1 | 查询 | 1219200 |
2 | 查询 | 1209930 |
3 | 更新 | 279770 |
4 | 更新 | 304898 |
每秒查询吞吐率(完成次数/s) | 242913 | |
每秒更新吞吐率(完成次数/s) | 58466.8 | |
总吞吐率(完成次数/s) | 301379.8 |
在四个线程进行读写测试时,平均每秒可以进行24.3万次查询,5.8万次更新,总体吞吐率为30.1万。
2. 八线程
读写测试是通过八个线程,其中四个线程持续做更新操作,另外四个线程做查询操作,持续运行10秒中,每个线程的性能和总体性能如下:
线程ID | 操作 | 操作次数 |
1 | 查询 | 628722 |
2 | 查询 | 625695 |
3 | 查询 | 621092 |
4 | 查询 | 593157 |
5 | 更新 | 158788 |
6 | 更新 | 163491 |
7 | 更新 | 170684 |
8 | 更新 | 173778 |
每秒查询吞吐率(完成次数/s) | 246866.6 | |
每秒更新吞吐率(完成次数/s) | 66674.1 | |
总吞吐率(完成次数/s) | 313540.7 |
可以看到同时进行读写测试时,平均每秒可以进行24.7万次查询,6.7万次更新,总体吞吐率为31.4万。
3. 总结
1:1读写操作的总体吞吐率:
可以看到,1:1读写操作的性能,4线程与8线程总体吞吐率相近。
${PageNumber}删除测试
1. 单线程
首先进行单线程的删除测试,在数据库中进行10000000次删除,每次删除一条记录,性能如下:
线程ID | 记录数 | 耗时(毫秒) |
1 | 10000000 | 156014 |
每条记录所花费的时间(微秒) | 15.6014 | |
每秒吞吐率(object/s) | 64096.81 |
单线程进行10000000次删除操作的耗时为156秒,每次查询花费时间为15.6微秒,每秒处理的操作数为6.4万。
2. 四线程
之后我们增加线程数为4.
四个线程进行10000000次删除操作,性能如下:
线程ID | 记录数 | 耗时(毫秒) |
1 | 2500000 | 90158 |
2 | 2500000 | 92504 |
3 | 2500000 | 93172 |
4 | 2500000 | 93239 |
插入10000000条记录所花费的总时间(秒) | 92.26825 | |
每条记录所花费的时间(微秒) | 9.226825 | |
每秒吞吐率(object/s) | 108379.6 |
四个线程进行10000000次删除操作的总耗时为92秒,平均删除每条记录耗时9.2微秒,每秒处理10.8万次删除操作。
3. 八线程
删除测试是通过八个线程,按照记录ID,同时删除数据库中记录,共10000000个对象,每个线程的性能和总体性能如下:
线程ID | 记录数 | 耗时(毫秒) |
1 | 1250000 | 91165 |
2 | 1250000 | 92365 |
3 | 1250000 | 91888 |
4 | 1250000 | 92916 |
5 | 1250000 | 93147 |
6 | 1250000 | 93273 |
7 | 1250000 | 94039 |
8 | 1250000 | 93723 |
查询10000000次的耗时(秒) | 92.8145 | |
每次查询的耗时(微秒) | 9.28145 | |
每秒吞吐率(object/s) | 107741.8 |
可以看到8个并发同时删除10000000条记录所花费的时间大概为92.8秒,平均每秒可以进行10.7万次删除。
4. 总结
查询操作的总体吞吐率:
可以看到,删除操作的性能,同样也是四个线程并发操作时,吞吐率最大。
以上测试都是每次操作都为一个事务,每次操作只涉及一条记录。
本文总结:
Altibase 定位为一个独立、标准化的通用数据库,支持SQL92完备级规范,支持ODBC、JDBC等标准接口,应用程序开发和部署支持上比较灵活,扩充起来比较有弹性。完整支持MVCC(多版本并发控制),可保证在高并发的多个事务中,每个事务读到的数据都具有逻辑上的一致性。Altibase将数据和控制信息都放在内存中集中管理,因此它所需的内存空间是数据文件大小的150%-200%,对内存开销较大。目前Altibase在计费系统上有较广的应用。