宽表在BI事务中比比皆是,每次建造BI体系时首先要做的便是准备宽表。有时体系中的宽表或许会有上千个字段,常常由于“过宽”逾越了数据库表字段数量约束还要再拆分。

为什么咱们乐此不疲地造宽表呢?首要原因有两个。

一是为了进步查询功能。现代BI一般运用联系数据库作为后台,而SQL一般运用的HASH JOIN算法,在相关表数量和相关层级变多的时分,核算功能会急剧下降,有七八个表三四层级相关时就能观察到这个现象,而BI事务中的相关杂乱度远远逾越这个规划,直接运用SQL的JOIN就无法到达前端立等可取的查询需求了。为了防止相关带来的功能问题,就要先将相关消除,行将多表事前相关好选用单表存储(也便是宽表),再查询的时分就能够不必再相关,然后到达进步查询功能的意图。

二是为了下降事务难度。由于多表相关尤其是杂乱相关在BI前端很难表达和运用。假如选用自动相关(依据字段类型等信息匹配)当遇到同维字段(如一个表有2个以上地区字段)时会“晕掉”不知道该相关哪个,表间循环相关或自相关的状况也无法处理;假如将众多表敞开给用户来自行选择相关,由于事务用户无法了解表间联系而几乎没有可用性;分步相关能够描绘杂乱的相关需求,但一旦前一步出错就要推倒重来。所以,不管选用何种办法,工程完结和用户运用都很麻烦。可是依据单表来做就会简单许多,事务用户运用时没有什么障碍,因而将多表组织成宽表就成了“自然而然”的工作。

不过,凡事都有两面性,咱们看到宽表优点而许多使用的一起,其缺陷也不容忽视,有些缺陷会对使用发生极大影响。下面来看一下。

宽表的缺陷

数据冗余容量大

宽表不符合范式要求,将多个表合并成一个表会存在许多冗余数据,冗余程度跟原表数据量和表间联系有关,一般假如存在多层外键表,其冗余程度会呈指数级上升。许多数据冗余不只会带来存储上的压力(多个表组合出来的宽表数量或许十分多)形成数据库容量问题,在查询核算时由于许多冗余数据参与运算还会影响核算功能,导致虽然用了宽表但仍然查询很慢。

数据过错

由于宽表不符合三范式要求,数据存储时或许呈现一致性过错(脏写)。比方同一个出售员在不同记载中或许存储了不同的性别,同一个供应商在不同记载中的所在地或许呈现对立。依据这样的数据做剖析成果明显不对,而这种过错十分隐蔽很难被发现。

别的,假如构建的宽表不合理还会呈现汇总过错。比方依据一对多的A表和B表构建宽表,假如A中有核算方针(如金额),在宽表中就会重复,依据重复的方针再汇总就会呈现过错。

灵敏性差

宽表本质上是一种按需建模的手法,依据事务需求来构建宽表(虽然理论上能够把一切表的组合都形成宽表,但这只存在于理论上,假如要实际操作会发现需求的存储空间大到完全无法承受的程度),这就呈现了一个对立:BI体系建造的初衷首要是为了满意事务灵敏查询的需求,即事前并不知道事务需求,有些查询是在事务开展过程中逐步催生出来的,有些是事务用户暂时起意的查询,这种灵敏多变的需求选用宽表这种要事前加工的处理办法极为对立,想要取得宽表的好就得献身灵敏性,可谓鱼与熊掌不可兼得。

可用性问题

除了以上问题,宽表由于字段过多还会引起可用性低的问题。一个现实表会对应多个维表,维表又有维表,并且表之间还或许存在自相关/循环相关的状况,这种结构在数据库体系中很常见,依据这些结构的表构建宽表,尤其要表达多个层级的时分,宽表字段数量会急剧增加,常常或许到达成百上千个(有的数据库表有字段数量约束,这时又要横向分表),试想一下,在用户接入界面假如呈现上千个字段要怎样用?这便是宽表带来的可用性差的问题。

总体来看,宽表的坏处在许多场景中常常要大于优点,那为什么宽表还许多横行呢?

由于没办法。一向没有比宽表更好的计划来处理前面提到的查询功能和事务难度的问题。其实只要处理这两个问题,宽表就能够不必,由宽表发生的各类问题也就处理了。

SPL+DQL消除宽表

凭借开源集算器SPL能够完结这个方针。

SPL(Structured Process Language)是一个开源结构化数据核算引擎,自身供给了不依赖数据库的强大核算才能,SPL内置了许多高功能算法,尤其是对相关运算做了优化,对不同的相关场景选用不同的手法,能够大幅进步相关功能,然后不必宽表也能实时相关以满意多维剖析时效性的需求。一起,SPL还供给了高功能存储,合作高效算法能够进一步发挥功能优势。

只要高功能还不够,SPL原生的核算语法不合适多维剖析使用接入(生成SPL句子对BI体系改造较大)。目前大部分多维剖析前端都是依据SQL开发的,但SQL体系(不必宽表时)在描绘杂乱相关核算上又很困难,依据这样的原因,SPL设计了专门的类SQL查询语法DQL(Dimensional Query Language)用于构建语义层。前端生成DQL句子,DQL Server将其转化成SPL句子,再依据SPL核算引擎和存储引擎完结查询返回给前端,完结全链路BI查询。需求留意的是,SPL只作为核算引擎存在,前端界面仍要由用户自行完结(或选用相应产品)。

宽表为什么横行?

SPL:相关完结技能

SPL怎样不必宽表也能完结实时相关以满意功能要求的方针?

在BI事务中绝大部分的JOIN都是等值JOIN,也便是相关条件为等式的 JOIN。SPL把等值相关分为外键相关和主键相关。外键相关是指用一个表的非主键字段,去相关另一个表的主键,前者称为现实表,后者称为维表,两个表是多对一的联系,比方订单表和客户表。主键相关是指用一个表的主键相关另一个表的主键或部分主键,比方客户表和 VIP 客户表(一对一)、订单表和订单明细表(一对多)。

这两类 JOIN 都触及到主键,假如充分运用这个特征选用不同的算法,就能够完结高功能的实时相关了。

不过很惋惜,SQL 对 JOIN 的界说并不触及主键,仅仅两个表做笛卡尔积后再按某种条件过滤。这个界说很简单也很宽泛,几乎能够描绘一切。可是,假如严厉按这个界说去完结 JOIN,理论上没办法在核算时运用主键的特征来进步功能,只能是工程上做些有限的优化,在状况较杂乱时(表多且层次多)常常无效。

SPL 改变了 JOIN 的界说,针对这两类 JOIN 别离处理,就能够运用主键的特征来削减运算量,然后进步核算功能。

外键相关

和SQL不同,SPL中明确地区分了维表和现实表。BI体系中的维表都一般不大,能够事前读入内存建立索引,这样在相关时能够少核算一半的HASH值。

关于多层维表(维表还有维表的状况)还能够用外键地址化的技能做好预相关。行将维表(本表)的外键字段值转化成对应维表(外键表)记载的地址。这样被相关的维表数据能够直接用地址取出而不必再进行HASH值核算和比对,多层维表仅仅是多个按地址取值的时间,和单层维表时的相关功能根本适当。

相似的,假如现实表也不大能够悉数读入内存时,也能够经过预相关的办法处理现实表与维表的相关问题,进步相关效率

预相关能够在体系启动时一次性读入并做好,今后直接运用即可。

当现实表较大无法全内存时,SPL 供给了外键序号化办法:将现实表中的外键字段值转化为维表对应记载的序号。相关核算时,用序号取出对应维表记载,这样能够取得和外键地址化相似的作用,相同能防止HASH值的核算和比对,大幅进步相关功能。

主键相关

有的现实表还有明细表,比方订单和订单明细,二者经过主键和部分主键进行相关,前者作为主表后者作为子表(还有经过悉数主键相关的称为同维表,能够看做主子表的特例)。主子表都是现实表,触及的数据量都比较大。

SPL为此选用了有序归并办法:预先将外存表按照主键有序存储,相关时次序取出数据做归并,不需求发生暂时缓存,只用很小的内存就能够完结核算。而SQL选用的HASH分堆算法杂乱度较高,不只要核算HASH值进行对比,还会发生暂时缓存的读写动作,运算功能很差。

HASH 分堆技能完结并行困难,多线程要一起向某个分堆缓存数据,形成共享资源冲突;某个分堆相关时又会消费许多内存,无法施行较大的并行数量。而有序归则易于分段并行。数据有序时,子表就能够依据主表键值进行同步对齐分段以保证正确性,无需缓存,且由于占用内存很少能够选用较大的并行数,然后取得更高功能。

预先排序的成本虽高,可是一次性做好即可,今后就总能运用归并算法完结 JOIN,功能能够进步许多。一起,SPL 也供给了在有追加数据时仍然坚持数据整体有序的计划。

关于主子表相关SPL还能够选用更有用的存储形式将主子表一体化存储,子表作为主表的集合字段,其取值是由与该主表数据相关的多条子表记载构成。这适当于预先完结了相关,再核算时直接取数核算即可,不需求比对,存储量也更少,功能更高。

存储机制

高功能离不开有用的存储。SPL也供给了列式存储,在BI核算中能够大幅下降数据读取量以进步读取效率。SPL列存选用了独有的倍增分段技能,相对传统列存分块并行计划要在很大数据量时(否则并行会受到约束)才会发挥优势不同,这个技能能够使SPL列存在数据量不很大时也能取得杰出的并行分段作用,充分发挥并行优势。

SPL还供给了针对数据类型的优化机制,能够明显进步多维剖析中的切片运算功能。比方将枚举型维度转化成整数,在查询时将切片条件转化成布尔值构成的对位序列,在比较时就能够直接从序列指定位置取出切片判别成果。还有将多个标签维度(取值是或否的维度,这种维度在多维剖析中许多存在)存储在一个整数字段中的标签位维度技能(一个整数字段能够存储16个标签),不只大幅削减存储量,在核算时还能够针对多个标签一起做按位核算然后大幅进步核算功能。

有了这些高效机制今后,咱们就能够在BI剖析中不再运用宽表,转而依据SPL存储和算法做实时相关,功能比宽表还更高(没有冗余数据读取量更小,更快)。

不过,只要这些还不够,SPL原生语法还不合适BI前端直接访问,这就需求合适的语义转化技能,经过合适的办法将用户操作转化成SPL语法进行查询。

这就需求DQL了。

DQL:相关描绘技能

DQL是SPL之上的语义层构建东西,在这一层完结关于SPL数据相相联系的描绘(建模)再为上层使用服务。行将SPL存储映射成DQL表,再依据表来描绘数据相相联系。

宽表为什么横行?

经过对数据表联系描绘今后形成了一种以维度为中心的总线式结构(不同于E-R图中的网状结构),中间是维度,表与表之间不直接相关都经过维度过渡。

宽表为什么横行?

依据这种结构下的相关查询(DQL句子)会很好表达。比方要依据订单表(orders)、客户表(customer)、出售员表(employee)以及城市表(city)查询:本年度华东的出售人员,在全国各出售区的出售额

用SQL写起来是这样的:

SELECT
 ct1.area,o.emp_id,sum(o.amount) somt
FROM
 orders o
 JOIN customer c ON o.cus_id = c.cus_id
 JOIN city ct1 ON c.city_id = ct1.city_id
 JOIN employee e ON o.emp_id = e.emp_id
 JOIN city ct2 ON e.city_id = ct2.city_id
WHERE
 ct2.area = 'east' AND year(o.order_date)= 2022
GROUP BY
 ct1.area,  o.emp_id

多个表相关要JOIN多次,同一个地区表要重复相关两次才能查到出售员和客户的所在区域,关于这种状况BI前端表达起来会很费劲,假如将相关敞开出来,用户又很难了解。

那么DQL是怎样处理的呢?

DQL写法:

SELECT
 cus_id.city_id.area,emp_id,sum(amount) somt
FROM
 orders
WHERE
 emp_id.city_id.area == "east" AND year(order_date)== 2022
BY
 cus_id.city_id.area,emp_id

DQL不需求JOIN多个表,只依据orders单表查询就能够了,外键指向表的字段当成属性直接运用,有多少层都能够引证下去,很好表达。像查询客户所在地区经过cus_id.city_id.area一向写下去就能够了,这样就消除了相关,将多表相关查询转化成单表查询。

更进一步,咱们再依据DQL开发BI前端界面就很容易,比方能够做成这样:

宽表为什么横行?

用树结构分多级表达多层维表相关,这样的多维剖析页面不只容易开发,一般事务用户运用时也很容易了解,这便是DQL的效能。

总结一下,宽表的意图是为了处理BI查询功能和前端工程完结问题,而宽表会带来数据冗余和灵敏性差等问题。经过SPL的实时相关技能与高效存储能够处理功能问题,并且功能比宽表更高,一起不存在数据冗余,存储空间也更小(紧缩);DQL构建的语义层处理了多维剖析前端工程的完结问题,让实时相关成为或许,,灵敏性更高(不再局限于宽表的按需建模),界面也更容易完结,使用规模更广。

SPL+DQL承继(逾越)宽表的优点一起改进其缺陷,这才是BI该有的样子。

SPL资料

  • SPL下载
  • SPL源代码