Google Supersonic列存储查询库的介绍、安装、测试
查询引擎库介绍:
http://www.infoq.com/cn/news/2012/10/Google-Supersonic/
Supersonic是一个面向列存储数据库的查询引擎库,它提供了一组数据变换原语。而且Google宣称,因为“大量使用了高速缓存感知算法、SIMD指令和矢量化执行,使之能够开发出现代超级流水线处理器的能力与资源”,这些数据变换原语“超级快速”。
Supersonic有以下主要特性:
- 高速缓存感知
- 指令流水线
- 使用SIMD(Single Instruction Multiple Data,单指令多数据)
- 定制数据结构
- 失效处理
- 支持标准的列存储操作
- 专门化的表达式
Supersonic支持大量的操作(operation),这些操作既可以用于整个表,也能组合为操作树:
- 聚合:SUM、MIN、MAX、COUNT、CONCAT、FIRST、LAST
- 计算:将表达式(下面有更多关于表达式的信息)转换为操作
- 过滤:过滤列存储表的行
- 生成:创建一定数量的没有列的行
- 限制:限制从前一操作所得结果的行数
- 排序:将前一操作的结果排序
与操作不同的是,表达式(expression)应用于行级,负责在单个的列值上执行真正的计算。表达式也可以组合成表达式树。下面列出一些表达式:
- 末端:叶节点,其中包含的是基本类型,如ConstInt32、ConstBool、ConstDataType、RandInt32等
- 算数运算:Plus、Minus、Multiply等
- 比较运算:Equal、Less、Greater、IsOdd等
- 日期/时间运算:Now、Day、Month、Year、Hour、Minute、Second、AddDays等
- 逻辑运算:And、Or、AndNot、Xor、Not
- 控制流:If、IsNull、IfNull、Case
- 数学运算:Exp、Sin、Cos、Abs、Round、Floor、Trunk、Sqrt、Power等
- 字符串:ToString、Concat、Length、Trim等
Supersonic使用C++编写,而且没有内置的数据存储格式,但是现在有“很强的意图”来创建一个。数据当前保存在内存中。
Supersonic查询引擎基于Apache License 2.0许可发布,可以从它的Google Code网站下载。为了说明针对列存储表如何使用操作与表达式,源代码中提供了大量的例子。
附图是Supersonic团队给出的,表示按如下方式处理一个行数为1M的表所得到的带有基准测试结果的操作树: 一个视图的获取要花费60微秒(速度为16.7G rows/s),随后过滤用掉1.03毫秒(速度为1M rows/s),后面是一个耗时25微秒的计算(速度为41.2M rows/s),然后结果与另一个过滤结合,整个测试耗时22.1 毫秒。
安装环境:
系统CentOS 6.2,gcc 4.3.2版本不足以安装(缺少constexpr),避免浪费时间,通过yum安装gcc 4.8.2的。
参考:http://blog.sina.com.cn/s/blog_48c95a190101b041.html
1、安装boost,主要依赖CPU Timer, 或者可以使用 ./b2 toolset=gcc cxxflags="-std=c++11"
wget http://nchc.dl.sourceforge.net/project/boost/boost/1.50.0/boost_1_50_0.tar.bz2
tar zjvf boost_1_50_0.tar.bz2
./bootstrap.sh --with-libraries=system,filesystem,log,thread,timer --with-toolset=gcc
./b2 toolset=gcc ./b2 install --prefix=/usr
tar zxf glog-0.3.3.tar.gz mv glog-0.3.3 glog cd glog ./configure make -j 2
tar zxf gflags-2.0.tar.gz mv gflags-2.0 gflags cd gflags ./configure make -j 2
tar zxf protobuf-2.5.0.tar.gz mv protobuf-2.5.5 protobuf cd protobuf ./configure make -j 2
tar zxf re2-20130115.tgz mv re2-20130115 re2 #这步貌似没有 cd re2 make -j 2
make install #避免后面link找不到
tar zvf supersonic-0.9.4.tar.gz mv supersonic-0.9.4.tar.gz supersonic cd supersonic
export GLOG_CFLAGS='-I../glog/src' export GLOG_LIBS='-L../glog -lglog' export CPPFLAGS=$CPPFLAGS' -I../glog/src' export GFLAGS_CFLAGS='-I../gflags/src' export GFLAGS_LIBS='-L../gflags -lgflags' export CPPFLAGS=$CPPFLAGS' -I../gflags/src' export PROTO_CFLAGS='-I../protobuf/src' export PROTO_LIBS='-L../protobuf/src -lprotobuf' export CPPFLAGS=$CPPFLAGS' -I../protobuf/src' export PROTOC=$(readlink -f ../protobuf/src/protoc) SO_PATH=$(readlink -f ../re2/obj/so) && \ export LDFLAGS=$LDFLAGS' -L../re2/obj/so -Wl,-rpath -Wl,'$SO_PATH export CPPFLAGS=$CPPFLAGS' -I../re2'
CXXFLAGS = -funsigned-char -O3 -mmmx -msse -msse2 -std=c++11 -lrt
./configure make -j 2 make check
check就相当运行所有的用例(程序)
===================
All 15 tests passed
===================
如果check发生依赖库问题, 检测依赖路径
vi ~/.bash_profile
LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/lib:/usr/lib64:/lib:/lib64:/usr/local/lib:/usr/local/lib64 export LD_LIBRARY_PATH
source ~/.bash_profile
所有安装包附件:https://files.cnblogs.com/files/hero4china/aa.zip
测试例子:
参考:http://blog.sina.com.cn/s/blog_48c95a190101bozi.html
把上面的glog,gflags,protobuf,re2,supersonic的目录进行了make install.
例子代码:mytest.cpp
#include <iostream> #include "supersonic/supersonic.h" using std::cout; using std::endl; using supersonic::BoundExpressionTree; using supersonic::Expression; using supersonic::Plus; using supersonic::AttributeAt; using supersonic::TupleSchema; using supersonic::Attribute; using supersonic::INT32; using supersonic::NOT_NULLABLE; using supersonic::FailureOrOwned; using supersonic::HeapBufferAllocator; using supersonic::View; using supersonic::EvaluationResult; using supersonic::SingleSourceProjector;
// 计算的规则,就是把两个列加起来 BoundExpressionTree* PrepareBoundexpression_r() { scoped_ptr<const Expression> addition(Plus(AttributeAt(0), AttributeAt(1))); TupleSchema schema; schema.add_attribute(Attribute("a", INT32, NOT_NULLABLE)); schema.add_attribute(Attribute("b", INT32, NOT_NULLABLE));
// 绑定 FailureOrOwned<BoundExpressionTree> bound_addition = addition->Bind(schema, HeapBufferAllocator::Get(), 2048); if(bound_addition.is_success()) { return bound_addition.release(); } return NULL; }
// 对两个数组进行了执行规则 const int32* AddColumns(int32* a, int32* b, size_t row_count, BoundExpressionTree* bound_tree) { TupleSchema schema; schema.add_attribute(Attribute("a", INT32, NOT_NULLABLE)); schema.add_attribute(Attribute("b", INT32, NOT_NULLABLE));
// 设置视图 View input_view(schema); input_view.set_row_count(row_count); input_view.mutable_column(0)->Reset(a, NULL); input_view.mutable_column(1)->Reset(b, NULL);
// 执行规则 EvaluationResult result = bound_tree->Evaluate(input_view); if(result.is_success()) { cout << "Column Count : " << result.get().column_count() << " and Row Count" << result.get().row_count() << endl; return result.get().column(0).typed_data<INT32>(); } return NULL; } int main(void) { int32 a[8] = {0, 1, 2, 3, 4, 5, 6, 7}; int32 b[8] = {3, 4, 6, 8, 1, 2, 2, 9}; // 定义 scoped_ptr<BoundExpressionTree> expr(PrepareBoundexpression_r());
// 执行 const int32* result = AddColumns(a, b, 8, expr.get()); if(result == NULL) { cout << "Failed to execute the addition operation!" << endl; } //结果验证 cout << "Results: "; for(int i = 0; i < 8; i++) { cout << result[i] << " "; } return 0; }
编译:g++ mytest.cc -std=c++11 -lsupersonic -lgflags -lglog -lprotobuf -lre2 -lboost_timer -Wno-deprecated -g -o mytest
执行:./mytest
输出结果:
Column Count : 1 and Row Count8
Results: 3 5 8 11 5 7 8 16