1.概述
1.1 应用场景
先说一下,为什么有缓存。大家都知道,报表的查询效率,是用户最为关心的问题之一。大家可能都对传统ERP中的报表查询效率颇有微辞,特别是当时间条件一放宽,经常就卡死在那里,搞的不好,把整个ERP服务都给拖崩溃了。于是乎,大家对善于做大数据分析的BI,就有了更为苛刻的预期,再加上大家动不动就在宣传资料上看到海量数据秒开的字样,也就会真的相信自己使用的时候也可以做到秒开。但事实上,报表查询的效率,是一个综合命题,需要在硬件资源,网络资源,系统资源,数据库资源,报表建模等多个方面进行优化。对于一般的企业级应用来讲,我们不会动不动弄个集群,外网的带宽也少有100M,服务器也就是普通的PC级服务器,数据库也大多数情况使用传统的关系型数据库,也就是说,追求效率的同时,我们要兼顾成本,那么,我们怎么才可以用较低的成本来获取较高的效率呢?奥威BI有集群、OLAP、Hadoop、内存计算等多种技术或方法来提高效率,但缓存却无异是成本最低、也不需要用户在使用上投入太多的方法之一(另外一个则是内存计算,后续会再另外撰文)。
什么是缓存呢?大家都知道,效率是存在物理极限的,比如,我们从一个千万条记录的表中执行一个select count(1) 都可能需要10秒,那么,这个10秒就是物理极限,从理论上来讲,我们的BI系统是不可能将这个10秒减少的。但是,对于报表的浏览用户来说,10秒却已经超过了5秒的无感等待时长,在体验上,就会有一种等待的感觉,这对于企业的高管来说,体验就差到难以接受了。既无法突破10秒的物理极限,又要让用户的体验时长小于5秒,那怎么办呢?其实我们可以取一个巧,就是在用户打开这张报表之前,提前加载好(这个过程仍然是需要10秒的,只是用户感觉不到而已),并将结果放到内存中,这样,用户打开的时候,就直接从内存中获取结果,而不再访问数据库,自然就获得了秒开的极致体验,并且,对于用户来说,还不需要额外做什么事情。——这个取巧的方法,就是缓存技术。
在奥威BI的缓存技术里,分为以下几种:
元数据缓存(支撑库缓存)
结果集缓存
报表整体缓存
智能缓存
快照
接下来,我们就分别介绍一下各项缓存技术。当然,最为关键的还是后面的各种应用场景下,如何结合缓存来理解并做出正确的操作。
2.缓存技术介绍
2.1 元数据缓存(支撑库缓存)
报表里的图表对象、图表对象对应的数据集构建器结构与最终生成的SQL语句等,都属于元数据缓存,简单的来理解,就是报表自己的框架。这些内容都保存在元数据库(支撑库)中,要展示一张报表,首先就是要将这些对象查询到,特别是根据数据集构建器生成SQL语句,里面有涉及到视图、表、字段、维度权限等等,查询比较多,这样,如果我们将用到查询支撑库的结果都缓存起来,每次使用时都直接在缓存获取,就会大大减少数据库查询的次数和查询时间。
元数据缓存完全由系统自动生成、销毁与更新,所以,无须手工干预。
2.2 结果集缓存
除了报表的框架以外,报表本身就是要将数据库中的各种结果查询并通过图表展示出来,所以报表中各图表控件(包括筛选控件)最终展现出来的结果,也是需要进行缓存的。
当下面的情况发生时,结果缓存会生成或变更:
数据集构建器变更
数据集刷新
筛选控件刷新
元数据字段树下拉
视图的预览
当报表的数据来源是数据仓库时,数据并不是实时更新的,通常情况下,是按天更新的,所以,我们的结果集缓存通常也可以在当天使用而不至于导致错误结果。但是,当晚上ETL调度导致数据仓库更新后,我们如果仍然用之前的缓存,显示的数据就是不对的,所以,我们需要将之前的结果集缓存销毁。在没有改变配置文件的情况下,系统默认每天22:00清除缓存,这样,就可以保证第二天第一次访问报表时,可以得到最新的数据结果。相关的设置,可以通过【系统管理】-【系统配置】-【系统管理】-【缓存设置】进行修改。除了可以修改每天什么时间清除缓存之外,还可以将这个功能关闭掉。那什么时候需要关闭这个功能呢?有的时候,我们这个系统就是用来做演示的,数据并不更新,所以,我们就会希望这个缓存一直存在,此时,就可以关闭重置缓存开关。
2.3 报表整体缓存
报表整体缓存是指不但缓存报表的框架,还缓存了报表中各图表控件的结果集,简单的来说,就是包括了前两种缓存。这样做的好处显而易见,就是在浏览报表时,只要根据报表ID,就可以将这张报表中所有的数据一次性从内存中读取并加载出来,这样的效率是最高的。
使其生效的相关设置:
(1)在报表属性中打开使用缓存。
(2)在【系统配置】-【系统管理】-【报表设置】中打开缓存设置开关(默认是开启的)
报表整体缓存默认也会每天定时(默认晚上10点)清除,设置与结果集缓存的设置相同,请参考上一节内容。
2.4 智能缓存
综合按用户、报表、结果集、权限、筛选习惯等,根据历史缓存记录以及使用频次的权重,自动进行缓存,缓存的内容包括支撑库、结果集与报表整体缓存。
那到底会有哪些报表会被智能缓存呢?关键是通过配置【智能缓存的权重】来调整。当你想让更多的用户报表被缓存起来,则将该权重调小(考虑到用户多、报表多的情况下,缓存的生成也是需要较长时间的,所以要综合权衡),反之,如果想关闭智能缓存功能,则改为100%即可。
又到底什么情况下会启动智能缓存这个功能,并更新缓存?首先,默认情况下,会在每天定时(默认晚上10点)清除缓存的时候,自动启用智能缓存功能,检查哪些用户浏览报表的行为符合上述权重的要求,就会被提前缓存。
但通常情况下,数据是通过ETL来完成数据更新,而一旦来源的数据发生了更新,那么,就需要重新更新缓存才对,所以,一般是在执行ETL完成后,就马上进行智能缓存。于是,在ETL中,有一个智能缓存的预设任务,可以将这个任务放到ETL调度的最后执行,一旦执行这个任务,系统会自动清除原来所有的缓存,并根据智能缓存规则重新缓存。
注:(1)必须设置报表属性【使用缓存】为开,智能缓存才生效。系统默认是开启的。
(2)建议在系统管理中,开启【报表整体缓存】。系统默认是开启的。
2.5 快照
快照与智能缓存类似,主要的区别在于,智能缓存是根据所有用户的浏览习惯来智能完成,而快照则是人为指定某个特定的用户及报表,并且只缓存了打开报表时的状态。
也就是说,快照是需要人为来生成的,所以,在ETL中,有一个快照的预置任务,一般会放在ETL结束后调度生成快照。
注:必须设置报表属性【使用缓存】为开,快照才生效。
3.应用场景
场景1:一边开发一边修改表结构,怎么办?
我们在开发的过程中,经常遇到一边开发一边修改表结构(如增加/删除/修改字段,包括修改字段类型),然后在前端报表设计页面却发现修改过的表结构并没有体现出来。比如增加了一个字段,在前端数据集构建器中却看不到,怎么办呢?这个问题很多人会以为与缓存有关系,其实这个问题与缓存无关,只是与元数据有关。在BI系统中,我们会将所用到的表结构保存在元数据库中,以便后续在使用的时候,不用老是去读数据源里面的表结构,以提高效率。而如果你修改了表结构,系统是不知道的,所以,需要你人为的去同步这个元数据信息。具体的操作方法为:
选择相应数据源,进入【编辑视图】-【所有表】,选择有修改过的表,点击【浏览】,系统即可将同步该表的元数据信息。(ETL的导入表也会影响)
场景2:一边做前端,一边修改表记录,怎么办?
我们在开发的过程中,经常遇到一边做前端,一边修改表记录,然后就会发现在设计报表时,数据并没有将修改过后的结果集体现出来,比如将原来性别字段的值从0/1改为男/女,或者增加了一些记录,在数据集构建器(待验证)或报表的图表对象中却没有变化,怎么办呢?
如果只是影响一个图表对象,则可以在数据集构建器中点击强制刷新按钮(可参考4.2章节内容),如果是影响整个报表很多个图表对象,此时可以调出右侧公共筛选区域,点击强制刷新缓存按钮(可参考4.1章节内容)。
场景3:修改了某个图表的某些UI属性,但是浏览时却仍然是老样子,怎么办?
因为启用了报表整体缓存导致,可以临时关闭报表的使用缓存,浏览正常后再打开使用缓存。——老版本才会有类似情况,V8.1.36版本之后,只要进入设计页面,就会清空报表整体缓存。
场景4:我想让每次打开报表的时候,都读取数据库里最新的数据,怎么办?
设置报表属性,打开【浏览刷新】,关闭【使用缓存】。如果这张报表因为数据量较大,访问效率比较慢的话,建议可以针对特定用户设置快照。
场景5:虽然开启了使用缓存,但打开某一张报表时有的时候仍然很慢,怎么办?
每天晚上10点会自动清除缓存,所以每个报表在第一次打开时,仍然是较慢,如果希望优化,则可以在ETL中加入快照或智能缓存调度。
场景6:使用了报表间隔刷新,使用缓存还有用吗?
一旦开启了报表间隔刷新,则使用缓存的配置无效。并且,为了避免因为间隔时间设置太小,而读取数据库的时间过长,而导致前端频繁刷新,所以,系统会采取延时显示的策略,具体举例如下:如间隔设置为5秒,则在5秒之后,系统会自动从数据库中取数,并将结果存入缓存,等第2个5秒后,系统首先先从第1次的缓存中将结果展现出来,同时,后台同时再从数据库中取数,将结果存入缓存,以备下个5秒时直接显示。简单一句来说,虽然设置的是5秒,但实际上显示的是上个5秒读取的数据。另外,如果报表中的数据从数据库里读取的最长时间为N秒,那么,间隔时间一定要大于N,最好是取2*N的时间。
场景7:给某个角色进行了数据授权,但报表浏览时该授权却无效?
如果报表时使用缓存的,则受结果集缓存的影响,仍然会保留上一次未授权时的缓存,此时,要在报表浏览界面强制刷新,或者关闭使用缓存,重新浏览报表正常后,再打开使用缓存。
4. 一般人我不告诉他
4.1 报表强制刷新
右侧公共筛选控件,强制刷新,可以将整个报表所有的结果集忽略当前缓存,重新从数据库中读取数据并计算结果,并且覆盖之前缓存。
4.2 数据集构建器的强制刷新
当修改了数据记录时,可以通过点击图示按钮,重新从数据库中执行相应的SQL,刷新结果,并将最新的结果集存入缓存。
4.3 报表间隔刷新
只有这种场景才使用:报表一直处于打开状态,而后台的数据是实时在变化的,为了让已经处于打开状态的报表,实时展示最新的数据变化,才需要使用间隔刷新。如生产看板。
一旦设置间隔刷新,报表的使用缓存属性自动失效。
如果设置间隔周期为5秒,则第1次不会改变,但会将结果写进缓存;第2次时会使用第1次生成的缓存显示数据,同时将本次查询结果写进缓存,如此反复,即间隔刷新会存在滞后1次的情况。
为避免间隔刷新周期太短,本次结果还未查询计算完,就开始下次刷新了,所以,本次显示的是上次的缓存,而本次查询计算的结果会异步在后台计算好后存在缓存中,供下次刷新时显示。
如果报表中的数据从数据库里读取的最长时间为N秒,那么,间隔时间一定要大于N,最好是取2*N的时间。
4.4 筛选控件缓存
筛选控件有一个浏览刷新的属性,当筛选控件是放在报表中参与布局时,相当于报表的一个普通控件,则跟随报表的相关属性走。只有当该筛选控件是在右侧的公共筛选控件时,该属性才会生效,即不走缓存,而是直接访问数据库,以保证数据是最新的。