2G内存搞定一亿数据的分析引擎

本文涉及的产品
云原生数据仓库AnalyticDB MySQL版,基础版 8ACU 100GB 1个月
简介: EuclidOLAP是一个可以在低配置服务器上执行上亿数据量分析并且快速响应和支持复杂查询的开源OLAP数据库。

运行大数据服务对服务器的配置要求是比较高的,相应的经济成本也不会低。本人做数据分析相关工作,一直在寻找高性能低成本的开源OLAP引擎,但是并没有找到,既然这样,那就自己搞一个。

EuclidOLAP

EuclidOLAP是我搞的一个开源OLAP多维数据库,它目前具有以下的几个特点:

  • 针对百亿级别数据量查询时可以达到毫秒级响应;
  • 能够支持非常复杂的查询,包括跨模型的关联查询;
  • 支持实时的增删改查;
  • 可以部署为集群模式,也能以单机模式运行在低配置服务器上。

在将来EuclidOLAP将会演化成基于云原生、容器、弹性资源的存算分离的架构模式。

EuclidOLAP的Github地址:https://github.com/EuclidOLAP/EuclidOLAP

剩下的内容分为两部分,首先简要介绍一下EuclidOLAP的数据模型与存储结构,然后在一台3G内存的低配服务器上运行一个EuclidOLAP示例并对一个一亿数据量的模型进行分析。

数据模型与存储结构

EuclidOLAP采用了立方体(Cube)和维度(Dimension)作为数据模型,如下所示:

维度就相当于坐标轴,你可以将一个关联个N个维度的Cube想象成一个N维立方体,同时把所有度量值想象成是存储于一个多维数组中。多维数组结构会带来一个严重的问题——内存容量爆炸,为了解决这个问题,像Cogons、Essbase这些传统多维数据库的解决办法是采用稀疏维和密集维结构:稀疏的几个维度被构建为索引,密集的维度则被构建为数据块——相对密集的更小的多维数组。

由于根据密集维构成的数据块也会存在数据空洞,所以上述的这种数据结构也会浪费掉一些内存。

EuclidOLAP的解决办法是在多维数组元素前面添加坐标偏移量,然后进行完全压缩,这样虽然也需要额外的内存来存储偏移量数据,但其消耗的内存相对于前面那两种结构来说是可以忽略不计的。

EuclidOLAP会同时构建一个索引结构,它会根据数据偏移量进行快速定位,以确定度量数据的坐标和聚合查询时的数据范围。

在逻辑层面,EuclidOLAP的这个索引结构很像图-2中稀疏维索引,但不同之处在于EuclidOLAP的这个索引结构可以表示从全部稀疏维到全部密集维的各种情况,我给它起了个名字——弹性索引结构。

在一个关联个N个维度的Cube中,弹性索引可以表示N+1种索引结构:

在逻辑模型层面,你还是可以将EuclidOLAP Cube中的度量数据想象成是存储于一个有着大量数据空洞的巨大的多维数组之中。

这种弹性索引结构同样存在问题,在新增数据时会导致整个数据结构的变化,我会在以后的文章中专门来介绍针对这个问题的解决办法。

接下来进入实践环节。

运行EuclidOLAP服务实例

EuclidOLAP中自带了一个一亿数据量的Cube,它需要占用不到2G内存,我在一台2400M内存的机器上运行过,你需要准备一台CentOS、Redhat、Ubuntu或Debian服务器,内存最好不低于3G。

EuclidOLAP自带了一个名为Nile Online Store的Cube,它关联了六个维度:日期(Date )、地区(Region )、商品(Goods )、支付方式(Payment Methods )、客户类型(Customer Types )、销售渠道(Sales Channels )。

点击这个链接查看这6个维度的详细结构:http://www.euclidolap.com/attachments/nos.html

这个Cube有一个度量值:Sales,为了演示方便,所有的明细度量值都是1。

EuclidOLAP支持多维数据库的标准语言——MDX(Multi-Dimensional Expressions ),它在语法结构上类似于SQL,不同之处在于MDX在语义层面直接描述多维结构,它对于复杂分析的支持能力要强于SQL。

按下面的步骤下载并运行EuclidOLAP服务:

wget https://sysbase.oss-cn-beijing.aliyuncs.com/EuclidOLAP-v0.1.6.1.tar.gz
tar zxvf EuclidOLAP-v0.1.6.1.tar.gz
cd EuclidOLAP
./bin/start.sh &

查看日志:

tail -n 5 log/euclid.log

当日志中显示了Net service startup on port 8760内容时表示EuclidOLAP已经成功运行。

第一个MDX是一个执行全汇总的查询

select
    [Measures].Sales on 0,
    Date.[ALL] on 1
from [Nile Online Store];

在EuclidOLAP目录中运行olap客户端工具:

./bin/olap-cli

执行MDX查询:

这个查询将全部明细数据汇总查出,结果是100000000。

第二个MDX对明细数据进行查询

它在商品维度(Goods )、支付方式维度(Payment Methods )、客户类型维度(Customer Types )和销售渠道维度(Sales Channels )上进行了限定,然后按日期维度(Date )和地区维度(Region )查看Sales度量值:

select
    {Date.[2022].Q1, Date.[2022].Q2, Date.[2022].Q3, Date.[2022].Q4} on 0,
    {Region.Europe.France, Region.Europe.Germany, Region.Europe.[United Kingdom]} on 1
from [Nile Online Store]
where
([Goods].[Foodstuff].[Drink].[Tea], [Payment Methods].[PayPal], [Customer Types].[New customers], [Sales Channels].[Direct sales]);

执行这个MDX将立即返回结果。

第三个MDX与第二个类似

它没有在日期和地区之外的其他维度进行限定,该查询将在其他四个维度上进行汇总。日期和地区维度分别指定了年份和洲级别的维度成员,这要比第二个MDX具有更高的汇总粒度。

select
    {Date.[2020], Date.[2021], Date.[2022]} on 0,
    {Region.Asia, Region.Europe, Region.[North America]} on 1
from [Nile Online Store];

第四个MDX是一个复杂逻辑的查询

它将按地区查询2022年总体销售额最高的那个季度的前三种畅销商品的销售数据:

select
    CrossJoin(
        TopCount(Date.[2022].Children, 1, [Measures].Sales),
        TopCount(LateralMembers([Goods].[Foodstuff].[Drink].[Tea]), 3, [Measures].Sales)) on 1,
Region.ROOT.Children() on 0
from [Nile Online Store];

最后说一下MDX这个东西。MDX 与SQL 语法相似,如同SQL 查询一样,每个MDX 查询都要求有SELECT、FROM 和可选的WHERE部分。SQL的语义模型描述Table结构,MDX的语义模型描述Cube结构,相同的一套业务模型可以放在SQL星型表结构中,也可以放在MDX Cube模型中,但是基于Cube使用MDX能更好的支持复杂且比SQL更加直观。关于MDX的详细介绍我也会发布在以后的文章中。

相关实践学习
AnalyticDB MySQL海量数据秒级分析体验
快速上手AnalyticDB MySQL,玩转SQL开发等功能!本教程介绍如何在AnalyticDB MySQL中,一键加载内置数据集,并基于自动生成的查询脚本,运行复杂查询语句,秒级生成查询结果。
阿里云云原生数据仓库AnalyticDB MySQL版 使用教程
云原生数据仓库AnalyticDB MySQL版是一种支持高并发低延时查询的新一代云原生数据仓库,高度兼容MySQL协议以及SQL:92、SQL:99、SQL:2003标准,可以对海量数据进行即时的多维分析透视和业务探索,快速构建企业云上数据仓库。 了解产品 https://www.aliyun.com/product/ApsaraDB/ads
目录
相关文章
|
23天前
|
存储 编译器 C语言
【C语言篇】数据在内存中的存储(超详细)
浮点数就采⽤下⾯的规则表⽰,即指数E的真实值加上127(或1023),再将有效数字M去掉整数部分的1。
|
4天前
|
存储 运维
.NET开发必备技巧:使用Visual Studio分析.NET Dump,快速查找程序内存泄漏问题!
.NET开发必备技巧:使用Visual Studio分析.NET Dump,快速查找程序内存泄漏问题!
|
8天前
|
NoSQL 程序员 Linux
轻踩一下就崩溃吗——踩内存案例分析
踩内存问题分析成本较高,尤其是低概率问题困难更大。本文详细分析并还原了两个由于动态库全局符号介入机制(it's a feature, not a bug)触发的踩内存案例。
|
14天前
|
Python
Python变量的作用域_参数类型_传递过程内存分析
理解Python中的变量作用域、参数类型和参数传递过程,对于编写高效和健壮的代码至关重要。正确的应用这些概念,有助于避免程序中的错误和内存泄漏。通过实践和经验积累,可以更好地理解Python的内存模型,并编写出更优质的代码。
10 2
|
13天前
|
NoSQL Java 测试技术
Golang内存分析工具gctrace和pprof实战
文章详细介绍了Golang的两个内存分析工具gctrace和pprof的使用方法,通过实例分析展示了如何通过gctrace跟踪GC的不同阶段耗时与内存量对比,以及如何使用pprof进行内存分析和调优。
45 0
Golang内存分析工具gctrace和pprof实战
|
27天前
|
编译器 C++
virtual类的使用方法问题之C++类中的非静态数据成员是进行内存对齐的如何解决
virtual类的使用方法问题之C++类中的非静态数据成员是进行内存对齐的如何解决
|
1月前
|
存储 算法 大数据
小米教你:2GB内存搞定20亿数据的高效算法
你好,我是小米。本文介绍如何在2GB内存中找出20亿个整数里出现次数最多的数。通过将数据用哈希函数分至16个小文件,每份独立计数后选出频次最高的数,最终比对得出结果。这种方法有效解决大数据下的内存限制问题,并可应用于更广泛的场景。欢迎关注我的公众号“软件求生”,获取更多技术分享!
144 12
|
10天前
使用qemu来dump虚拟机的内存,然后用crash来分析
使用qemu来dump虚拟机的内存,然后用crash来分析
|
1月前
内存的数据
va的ava的va的ava的内存需要划分成为5个部分: 1.栈(Stack)存放的都是方法中的局部变量。方法的运行一定要在栈当中运行。 2.堆(Heap)凡是new出来的东西,都是在堆当中 堆内存的东西都有一个地址值:16进制 堆内存的数据,都有默认值。规则: 整数 默认是0 浮点 默认0.0 字符 默认'\u0000'
27 3

热门文章

最新文章