分组是数据库的常见运算,无论数据如何准备,通常都需要将所有数据遍历。建立索引这时是不起作用的,存储格式才是决定遍历效率的主要因素。数据库中数据的存放虽然是二进制格式的,但普遍IO性能差,库内遍历快,外部取数都很慢。
下面用Oracle来举个例子,数据如下:
ORDERID CLIENT SELLERID AMOUNT ORDERDATE NOTE
1 287 47 5825 2013-05-31 gafcaghafdgie f ci…
2 89 22 8681 2013-05-04 gafcaghafdgie f ci…
3 47 67 7702 2009-11-22 gafcaghafdgie f ci…
4 76 85 8717 2011-12-13 gafcaghafdgie f ci…
5 307 81 8003 2008-06-01 gafcaghafdgie f ci…
6 366 39 6948 2009-09-25 gafcaghafdgie f ci…
7 295 8 1419 2013-11-11 gafcaghafdgie f ci…
8 496 35 6018 2011-02-18 gafcaghafdgie f ci…
9 273 37 9255 2011-05-04 gafcaghafdgie f ci…
10 212 0 2155 2009-03-22 gafcaghafdgie f ci…
…
实际数据量已经超过了数据库的最大内存(数据总量为 25G,Oracle 可用的最大内存为 12G)。使用Oracle的Parallel Execution来完成分组汇总,SQL大概这样:
select client,sellerid,count(orderid),sum(amount) from orders group by client,sellerid
这个SQL执行耗时:210秒。
同样的环境、同样的数据,用集算器来处理,耗时约65秒,代码如下:
A | |
1 | =$(esProcOdbc) select client,sellerid,count(orderid),sum(amount) from orders.btx group by client,sellerid |
后者速度快是因为使用了集算器集文件(二进制文件)作为数据存储,正如之前提到的数据存储格式直接影响遍历的性能,关于存储格式、特点、性能排名如下表:
存储格式 | 特点 | 性能排名 |
二进制 | 占用空间最小,解析最快 | 1 |
文本 | 文本的好处是通用,但性能不好 | 2 |
数据库 | 也是二进制,但普遍IO性能差,库内遍历快,外部取数都很慢 | 3 |
处理大量数据时,性能优化的第一步,往往是挑选合适的存储格式。数据库的存储十分宝贵,为了节约存储,提高运算性能,可将单纯用作OLAP场景的那些数据搬到数据库外部,使用更高性能的存储格式存放数据。感兴趣可以参考:性能优化教案—遍历
集算器还很容易嵌入到Java应用程序中,Java如何调用SPL脚本有使用和获得它的方法。
关于集算器安装使用、获得免费授权和相关技术资料,可以参见如何使用集算器。