cover_image

从模板到指标服务:解锁AI时代的数据新可能

有赞技术 有赞coder 2024年11月13日 10:18
图片

点击关注“有赞coder

获取更多技术干货哦~

图片

作者:家龙

部门:数据中台


一、背景

随着公司业务不断地发展,我们推出了众多数据产品以满足商家在各种经营场景下的数据分析需求,然而,这些数据产品在应对复杂用户问题时,仍然缺乏足够的便捷性和灵活性。为此,我们尝试结合大语言模型(LLMs)构建交互式智能问答类的数据产品。然而,当数据产品与AI结合后,传统的烟囱式开发模式,即为满足各自数据产品需求的定制化开发,已无法支持AI灵活的数据查询需求。在这种背景下,指标服务应运而生。
  分析过往烟囱式的数据服务会发现存在以下问题:
  • 各服务间指标口径不一致
  • 数据服务复用率低
  • 数据服务开发效率低,维护成本高
  • 数据链路不清晰,问题排查链路长

图片

充满各种血缘关系的烟囱式数据服务

对此我们设计了一套新的数据服务,设计的目标为

  • 各数据服务指标一致性

  • 指标的可复用:指标定义一次即可多次复用

  • 数据模型可复用:相同粒度的数据指标不再重复定义与建设

  • 数据服务开发的效率提升与可扩展性

  • 可为AI提供元数据与灵活数据查询的指标型数据服务


    图片


    统一的指标查询服务斩断万千表、API关联关系的麻绳


    本文会从历史的数据服务架构、新的数据服务如何演进且如何在业务上产生效果这三方面进行分享。

二、当前数据服务架构

图片

上述架构图中数据服务层有:
  1. OneService数据服务:以mybatis模板为核心的表级别数据服务,下文简称为OS数据服务
  2. 数据服务单元:为具体某个数据产品提供服务,根据业务流程串联多个OS数据服务的产品级数据服务

2.1 表级别数据服务的缺点

2.1.1 Mybatis模板服务示例

指标口径与数据源选择绑定在模板代码中的OS数据服务

select    sum(xxx) AS PV,    count(DISTINCT xxx) AS UV,    count(distinct xxx) AS NEW_UV,    sum(xxx) AS STAY_TIME_AVG,    sum(xxx) * 1.0 / count(DISTINCT xxx) AS PER_CAPITA_BROWSING,    count(DISTINCT xxx) AS SHARE_TOTAL_UV,    count(DISTINCT xxx) AS ADD_CART_UV,    count(DISTINCT xxx) AS ORDER_UV,    sum(xxx) as ORDER_AMOUNT,    sum(xxx) as PAY_AMOUNT,    count(distinct xxx) as PAY_CNT,    count(distinct xxx) as ORDER_CNTfrom    dm.xxxxwhere                 partition >= #{startDay}        and                 partition <= #{endDay}
and team_id = ${teamId}
<if test="firstChannel != null "> and first_channel=#{firstChannel} </if> <if test = "secondChannel"> and second_channel=#{secondChannel} </if> <if test = "thirdChannel"> and third_channel=#{thirdChannel} </if> <if test = "fourthChannel"> and fourth_channel=#{fourthChannel} </if>

2.1.2 以OS为核心的数据服务开发流程

图片

上述流程对于开发同学会有以下的疑问和痛点

图片

2.1.3 表级别服务缺点

1. 各服务间指标口径不一致
a、指标口径无处管理,导致指标不统一。比如: 
支付金额口径A=自销支付金额+三方支付金额+打包费
支付金额口径B=自销支付金额
同一店铺的不同模块可能引用不同口径,导致数据指标无法对齐。
b、数据源弱管控。同一指标可以引用不同数据源,比如:
模块A的访客数引用自mysql(精确去重)
模块B的访客数引用自kylin(非精确去重)
2. 数据服务复用率低
a、表级别服务,指标定义无法复用
b、面向某一个场景的API设计,不能灵活满足不同上层业务需求,一张DM表会构建出N个数据服务
3. 数据服务开发效率低,维护成本高
a、维护的可扩展性差
  • 没有指标级别数据血缘,无法快速定位某个指标取自哪张表,口径是什么
  • 模型变更上层服务也要相应进行变更,对于一张一对多的数据表,模型的变更将会连带多个数据服务都进行变更
b、指标重复定义,SQL模板重复编写,开发效率低
c、复杂场景SQL模板编写复杂,比如累计指标、各类衍生指标一起查询,并按照某个指标排序
4. 数据链路不清晰,问题排查链路长

图片


三、业务视角下的数据服务需求

一切数据服务都是为业务服务的,因此我们从数据产品的业务视角去看业务上需要的数据服务能力是什么,能否从业务视角去为上面的问题解决提供新的思路。
业务视角:
  1. 我们要观察的事物:指标,用于衡量事物发展程度帮助业务做出决策
  2. 我们观察事物的角度:维度
  3. 我们观察事物的限定条件:过滤条件

图片

从业务视角来看对于数据服务,我们需要提供的不是SQL,不是具体的物理表,也不是不能明确表达指标和维度信息的API名称。表模型和API等只是技术实现手段,不属于业务层面。业务上需要的是以指标+维度+过滤条件等条件为核心要素,以指标为原子能力提供灵活的数据服务。至于表模型、表级别API的构造可以下沉至数据服务框架中,不对外进行暴露。

图片

四、指标服务设计

4.1 Headless BI

4.1.1 BI的语义层

常见的BI工具通常包含一层语义层,它将物理数据模型转化为逻辑模型,定义模型的维度和度量,并在此基础上创建指标。

图片

逻辑模型构建

图片

模型定义

指标定义可以感知上下文(模型信息、其他指标定义),同时指标可以根据已定义的指标进行二次计算生成衍生指标。

图片

指标上下文感知

4.1.2 Headless BI

图片

常规的BI系统中,语义层通常与可视化部分紧密绑定,导致其他数据消费工具无法复用。Headless BI的理念是将BI的语义层独立出来,与BI工具的可视化部分解耦。通过在数据模型和数据消费者之间构建一层独立的指标语义层,为下游多个数据消费者提供统一、高性能、开放的数据接口,从而实现下游数据消费者指标口径上的一致性。
图片

4.2 基于Headless BI的数据模型虚拟化的指标服务

图片
对于上面的业务痛点,我们基于Headless BI的理念构建以指标语义层为核心、以虚拟数据模型为底层能力的灵活、指标口径统一的指标服务。

4.2.1 元数据管理

在元数据管理方面,我们将其分为以下几个部分:公共的维度和度量管理、数据模型管理、以及指标定义,为构建出虚拟的包含全域数据的超大宽表提供基础元数据以及全局统一的指标定义。
  1. 公共度量、维度管理

公共度量和维度作为全局度量与维度的管理字典,用于生成统一的度量和维度,并支持维度值的管理,方便进行维度值的检索,进而在后续的AI数据查询中发挥作用。为确保公共度量和维度的唯一性,组织内部需要达成共识,避免出现同义不同名的情况。
  1. 模型管理与定义

    模型管理主要负责对物理模型进行建模和管理,包含以下几个方面:

    1. 模型数据源:维护和管理数据模型的数据源。

    2. 模型数据时效性:配置模型是否包含实时数据、是否包含离线数据等。

    3. 模型字段管理:将模型字段与公共度量和维度进行映射。

    4. 模型优先级配置:支持手动设置模型的优先级。

  2. 指标定义

定义了公共维度、公共度量后,我们基于这些元数据进行指标口径定义,不同于常规BI的指标定义上下文,这里不再和具体的物理表模型关联。

图片

指标上下文

指标定义可分为:原子指标、派生指标、复合指标三类。下面对这三类指标的定义进行解释。
  1. 原子指标
    指标口径由公共度量和算子组成。为了消除同义不同名的问题,原子指标的公共度量+算子具有唯一性。
  2. 派生指标

    派生指标引用原子指标+公共维度过滤条件作为指标口径的定义。派生指标引用的原子指标+过滤条件具有唯一性。

  3. 复合指标
    复合指标引用原子/派生指标进行四则运算。复合指标的计算表达式具有唯一性。

除了指标定义外,我们还将指标相关知识录入到系统中,比如指标公式的拆解、指标所属业务节点等,为后续指标波动自动化识别提供基础业务知识。


4.2.2 数据模型虚拟化与数据查询实现

  上文介绍了元数据管理模块,这一小节会介绍如何对有赞数据模型进行虚拟化以及查询流程的实现。

1、设计思路

在介绍数据模型虚拟化之前我们先简单回顾下数据集市层数据模型的建设,数仓为了有效管理数据,对数据按主题域进行组织,划分到各个表中。

图片

有赞数仓架构

传统的数据集市设计是基于业务分析场景进行数据加工,对跨域的指标进行整合生成集市层的宽表,再选择合适的OLAP组件进行加速,最终基于OLAP上进行数据服务的提供。然而,这种设计存在一些缺点:

  1. 指标重复建设指标被不断地复制复制过程中可能存在特殊逻辑的加工导致各个数据集市的指标不统一,数据集市中很多字段会被重复建设。

  2. 数据模型管理复杂:由于不断复制,导致数据集市层的数据模型无序增长,管理复杂。

  3. 指标下钻分析复杂同一指标的不同粒度、不同维度可能会散落在不同的表,下钻需要自行维护指标和表的血缘关系。

  4. 缺乏跨数据源查询能力:无法进行跨数据源的查询。

  5. 宽表自身问题:木桶问题、扩展性差。

为了提升指标定义的作用范围,降低指标下钻分析的复杂度,消除数据集市中重复建设问题,我们在逻辑表的基础之上构建了虚拟数据模型层。虚拟数据模型层以公共维度和公共度量作为表元数据对外提供服务,屏蔽底层物理数据模型,根据公共维度和公共度量与物理模型之间的映射关系,构建出虚拟的包含全域数据的超大宽表

在查询时,虚拟的超大宽表会根据查询条件自动选择出匹配查询的数据模型列表,然后根据元数据关系构建出逻辑表,通过逻辑表进行数据查询。这种通过模型血缘关系实现数据模型自动选择的方式,有效提升了数据模型的复用,保证了数据指标查询时查询执行的唯一性,从而保证指标口径的一致性。同时,由于底层复用逻辑表的能力,实现物理数据源的语法适配和统一逻辑层跨数据源数据查询以及查询优化等能力,在宽表的易用性、高性能和扩展性之间取得了平衡。

图片

基于数据虚拟化的查询流程

2、数据模型设计录入与选择逻辑

2.1 数据模型设计
为避免在数据仓库层将各个指标维度拷贝至数据集市(DM)宽表中,指标服务平台的数据模型遵循数据仓库的维度建模原则,将事实表按业务域进行划分和建模,以尽可能确保指标和维度组合的唯一性。此外,在新模型录入系统时,平台会对数据模型进行冲突检测,以确保数据的一致性和准确性。

2.2 查询时数据模型选择逻辑

通过解析查询的DSL参数和指标元数据,我们可以确定当前查询所需的维度和度量组合。解析完成后,对物理数据模型进行筛选,将符合条件的物理模型按照度量分组。接下来,根据物理表的元数据信息计算查询代价,并结合部分人工配置的规则条件,对模型列表进行排序,最终在每个分组中选出最优的数据模型,将这些模型映射到逻辑表中。

3、可执行的逻辑表生成

对于刚才筛选出来的最优数据模型组合我们将其元数据根据逻辑表规范映射出一张逻辑表,并将逻辑SQL提交给逻辑表执行。逻辑表可以认为是一种根据元数据的关联关系自动生成的数据库视图,但不仅仅是视图,包含以下核心能力

    1. 跨引擎的查询能力

    2. 多数据源方言适配、并发物理查询

    3. 查询优化,按需构建查询视图,物理查询下推, order by查询优化等能力

    4. 同维指标合并,逻辑宽表结果返回,屏蔽跨域模型设计带来的查询复杂性

4、查询编排

指标服务旨在为业务服务,简化取数难度,因此一些常用的业务逻辑会被指标服务所包含,进行查询的编排,比如
    1. 累计指标在进行范围时间查询时仅需要查询结束时间
    2. 同环比数据查询并合并按指标进行合并、趋势数据查询
    3. 分页数据询时对分页结果进行趋势数据查询

4.2.3 指标服务接口

基于上述分析的业务要素,我们设计了一套DSL定义,用于构建统一的指标服务接口。业务方根据约定传入指标、过滤条件等,同时会将同环比、趋势等常见分析进行连带查询和数据结果合并。

图片

商品指标查询入参

图片

指标结果返回

4.2.4 新的服务整体架构

图片

五、新的指标服务在有赞的应用

图片

5.1 数据报表

5.1.1 报表应用

基于新的指标服务平台,我们可以快速创建数据报表。通过使用预定义的指标和维度,简单数据报表的构建速度提升了数倍。原先需要两三人日才能完成的数据报表服务,现在缩减到小时级别即可构建完成。

图片

数据报表

5.1.2 自助取数

我们基于指标服务构建了一套自助取数产品,对外屏蔽了底层物理模型。商家可以自行配置所需的指标和维度进行数据导出,极大地提升了数据获取的自主性和灵活性。

图片

维度选择

图片

指标选择

图片

样例数据展示

5.1.3 收益

  1. 指标可复用性强,指标口径强收敛,各报表间指标口径统一

  2. 指标维度扩展性强,元数据驱动,增加维度时不再需要调整数据服务API

  3. 开发提效,简单数据报表服务构建速度提升数倍


图片

数据开发流程提效

5.2 大模型的Tools,帮助大模型取数

5.2.1 大模型接入

为了提升商家获取数据的能力,我们提供了对话式的数据指标查询服务。一种经典的实现方案是通过LLM(大型语言模型)解析自然语言查询(NLQ),将其转换为SQL(NL2SQL),然后交由底层数据库执行。

图片

然而,这种方案存在以下问题:

  1. 指标口径不准确:在处理复杂指标查询时,LLM可能无法准确理解指标口径,从而导致错误的指标结果。

  2. LLM幻觉:LLM有时会基于自身的知识生成错误的SQL查询,在某些场景下会出现幻觉。

  3. 不具备复杂指标计算的能力:对于跨域等指标难以拆分查询逻辑并对查询结果二次计算能力差,计算不准确。

为了解决上述问题,我们采用新的技术方案:让LLM对接指标服务语义层,以指标、维度这些大模型擅长解析的语义内容作为DSL的参数,模型的选择、指标口径、查询SQL生成等收敛在指标服务中,避免LLM产生幻觉并且便捷地获取口径准确的数据指标,降低LLM的取数难度。

DSL查询示例:

指标:支付金额、支付人数、访客数
时间:2023-11-09
维度:店铺

图片

5.2.2 应用案例

  1. 自由看数

图片

  1. 诊断分析

图片

图片


5.3 数据洞察

当一个指标产生波动时,我们经常会分析是哪些核心的维度以及对应的维度值导致的指标波动。因此我们需要提供一个通用的指标自动化波动分析产品。
指标服务层实现了数据模型的虚拟化,提供了基于指标的业务知识(关联公式等),因此我们只需将核心放在洞察实现上,和指标服务的指标和维度元数据进行交互,便捷地进行指标下钻,不再关心底层物理模型,从而实现基于指标元数据的通用自动化指标波动洞察。

图片


六、展望和总结

指标服务平台通过对指标的统一定义、数据模型的虚拟化,实现了查询层指标口径的强一致与指标级数据服务快速构建,一定程度解决了业务痛点并在新业务上进行了落地。但当前只做了指标管控、指标使用,不涉及数据生产、自动物化加速等,后续会不断增强该部分能力。






‍‍

继续滑动看下一个
有赞coder
向上滑动看下一个