Metabase学习教程:模型-2

事实表分析引擎

如何根据实际分析用例为事实表建模。

目标数据建模是为了快速(用于处理查询的引擎),以及容易(针对编写这些查询的人)获取数据。

大多数数据仓库实践是为了强调速度。分析引擎(一个术语 popularized by dbt,有时也会捆绑到术语中全栈分析)是为可用性数据建模的过程。即使这不是你所说的,无论何时当你需要把一个策展数据集,一个分段或指标,或仪表板与他人协同,都可以实践分析引擎。

本教程将向您展示如何将分析引擎方法应用于数据仓库更具体地说,对于一种称为事实数据表.

介绍

维度表包含一个时间点的数据快照,例如在工作日结束时,您拥有的部分完成的杯子的数量。

| time                   | total mugs |

|---------------------|------------|

| 2022-08-16 17:30:00 | 3            |

事实数据表包含一个历史信息,比如你一天喝咖啡的速度。

| time                   | mug       | coffee remaining |

|---------------------|----------|------------------|

| 2022-08-16 08:00:00 | 1        | 100%             |

| 2022-08-16 08:01:00 | 1        | 0%               |

| 2022-08-16 09:00:00 | 2        | 100%             |

| 2022-08-16 12:00:00 | 3        | 100%             |

| 2022-08-16 12:30:00 | 3        | 99%              |

| 2022-08-16 17:30:00 | 3        | 98%              |

事实表和维度表依据星型模型(或密切相关的雪花模型)在数据仓库中组织信息。

如果出现以下情况,您可能需要构建事实表:

  • 您的数据源(生成数据的系统,如应用程序数据库)只存储当前信息快照,方法是将其保存在前一个快照上。
  • 你正在创建一个支持嵌入式分析的数据集为您的客户。独立的事实表非常适合自助分析,因为它们可以覆盖广泛的用例不依赖连接。

但是在我们开始之前,让我们在你每天的咖啡因总量中再加一杯,我们还有很多要做的!

| time                   | total mugs |

|---------------------|------------|

| CURRENT_TIMESTAMP() | n+1        |

概述

在本教程中,我们将使用维度表account,例如从CRM中获取的维度表。让我们假设一下account维度表存储客户的当前状态,当前状态由应用程序更新。

这个account表如下所示:

| id               | country     | type       | status    |

|------------------|-------------|------------|-----------|

| 941bfb1b2fdab087 | Croatia     | Agency     | Active    |

| dbb64fd5c56e7783 | Singapore   | Partner    | Active    |

| 67aae9a2e3dccb4b | Egypt       | Partner    | Inactive  |

| ced40b3838dd9f07 | Chile       | Advertiser | Test      |

| ab7a61d256fc8edd | New Zealand | Advertiser | Inactive  |

第1部分:设计事实表

基于account,我们需要考虑人们可能会问的关于客户帐户随时间变化的分析问题。自从account表包含status字段,我们可以回答以下问题:

  • 每个月新增多少个账户?
  • 每月有多少客户流失(变为不活跃)?
  • 客户群的流失率是多少?

第2部分:实现事实表

从数据存储在account创造fact_account,我们将编写一个SQL脚本:

  1. 初始化fact_account今天的account数据。
  2. 获取中的行的快照account(假设它被另一个系统更新)。
  3. 比较每天的account中的历史数据快照fact_account.
  4. 在中插入新行fact_account对于自前一天快照后更改的每个帐户。

第3部分:使用常见用例测试事实表

为了检查我们的事实表在实践中是否有用,我们将使用Metabase设置它,并尝试回答我们所有的三个示例分析问题。

第4部分:改进事实表性能

本教程的最后一节将让您了解在扩展事实表以容纳更多历史记录(和更多问题!)时迭代它的外观。

如何遵循本教程

如果您想将下面的步骤应用于您自己的数据,我们建议您使用由源系统定期更新的维度表,以及您选择的数据库或数据仓库.

在本教程中,我们将使用Metabase伙伴驱动程序Firebolt进行测试Firebolt是一个数据仓库,它使用了slightly modified SQL DDL将数据加载到旨在使查询运行更快的格式.

如果您跟随自己的数据,您的SQL语法可能与示例代码不完全匹配。有关更多信息,请查看常用SQL方言参考指南.

设计事实表

基本事实图式

首先,对于事实表我们要起草一份架构,我们称之为fact_account。将架构放在如下表所示的可视引用中可以更容易地验证fact_account将支持我们想要进行的查询(即人们想要回答的分析问题)。对于新手来说,可视参考也可以作为以后的有用资源fact_account.

在本例中,我们将保留account。如果需要省略任何列,则可以通过数据模型页Metabase中。与在开始时从模式中排除太多列相比,在Metabase中隐藏列的破坏性更小,因为每次需要恢复列时,我们都必须重新生成架构。

我们还将包括一个名为更新时间指示向表中插入行的时间戳。在实践中,更新时间可用于估计对帐户进行更改的日期或时间。

此添加基于以下假设:account属性可以更改,除了ID。例如,给定帐户的状态可以从活跃的不活动,或类型账户的合伙人广告主.

基本fact_account模式示例

| Column name     | Data type | Description                                                  | Expected values                                   |

|-----------------|-----------|--------------------------------------------------------------|---------------------------------------------------|

| id              | varchar   | The unique id of a customer account.                         | 16 character string                               |

| status          | varchar   | The current status of the account.                           | Active, Inactive, or Test                         |

| country         | varchar   | The country where the customer is located.                   | Any of the "English short names" used by the ISO. |

| type            | varchar   | The type of account.                                         | Agency, Partner, or Advertiser                    |

| updated_at      | datetime  | The date a row was added to the table                        |                                                   |

更好的事实模式

为了检查模式的可用性,我们将为我们的一个分析问题编写一个伪SQL查询:

-- How many new accounts have been added each month?

WITH new_account AS (

    SELECT

        id,

        MIN(updated_at) AS first_added_at -- Infer the account creation date

    FROM

        fact_account

    GROUP BY

        id

)

SELECT

    DATE_TRUNC('month', first_added_at) AS report_month,

    COUNT(DISTINCT id) AS new_accounts

FROM

    new_account

GROUP BY

    report_month;

当前的fact_accountschema需要一个额外的步骤来获取(或估计)每个帐户的创建时间戳(在这种情况下,估计对于已经处于活动状态的帐户是必要的)之前我们开始保留历史)。

如果我们只需在fact_account架构。但是添加列将增加表的复杂性(某人理解和查询它所需的时间),以及SQL脚本的复杂性(更新表所需的时间)。

帮助我们决定是否值得在fact_account架构中,我们将考虑创建时间戳是否可以用于有关帐户的其他类型的分析问题。

帐户的创建时间戳也可用于计算:

  • 账户的年龄。
  • 重要事件发生的时间(如客户流失或停止活动所需的天数)。

这些指标可以应用于有趣的用例,比如减少客户流失计算贷款价值比,所以这可能是值得的fact_account.

我们将添加列is_first_record使我们的模式保持流线型。此列将标记与事实数据表中帐户的最早条目相对应的行。

如果您计划创建一个事实表以简化自助服务(例如事实表包含通常在维度表中捕获的信息),您还可以为is_latest_record。此列将帮助用户筛选fact_account对于当前数据(除了历史数据),以便他们可以使用同一个表快速回答问题,例如:到目前为止,我们有多少活跃账户?

使用此约定可以使查询速度变慢,但在首次推出自助服务时更容易采用(因此人们不必记住事实表和维度表之间的连接)。

更好的fact_account架构

| Column name     | Data type | Description                                                         | Expected values                                   |

|-----------------|-----------|---------------------------------------------------------------------|---------------------------------------------------|

| id              | varchar   | The unique id of a customer account.                                | 16 character string                               |

| status          | varchar   | The current status of the account.                                  | "Active", "Inactive", "Test", or "Trial"          |

| country         | varchar   | The country where the customer is located.                          | Any of the "English short names" used by the ISO. |

| type            | varchar   | The type of account.                                                | "Agency", "Partner", or "Advertiser"              |

| ...             | ...       | ...                                                                 |                                                   |

| updated_at      | datetime  | The date a row was added to the table                               |                                                   |

| is_first_record | boolean   | TRUE if this is the first record in the table for a given id        |                                                   |

| is_latest_record| boolean   | TRUE if this is the most current record in the table for a given id |                                                   |

初始化事实表

为了实现事实模式,我们将从创建一个空的fact_account用于存储account表快照随时间变化。

我们使用的是Firebolt数据仓库,因此我们将从Firebolt控制台。我们将选择SQL工作区>新脚本,并写下:

-- Create an empty fact_account table in your data warehouse.

CREATE FACT TABLE IF NOT EXISTS fact_account

(

    id                  varchar

    status              varchar

    country             varchar

    type                varchar

    updated_at          timestamp

    is_first_record     boolean

    is_latest_record    boolean

);

注意FireboltDDL包括FACT关键字(可以在标准SQL DDL中排除它)。

如果您正在使用用于接收数据的同一个SQL脚本创建事实表,那么可以遵循注释良好的SQL脚本模板导入脚本可折叠右侧边栏上的按钮。

接下来,我们将填充fact_account包括往来账户表中的所有信息。可以在创建事实表的同一个SQL脚本中包含以下语句:

-- Put an initial snapshot of data from "account" into "fact_account".

-- Add "quality of life" columns to make the data model nicer to work with.

INSERT INTO fact_account (

    SELECT

        *,

        CURRENT_TIMESTAMP() AS updated_at,

        is_first_record = TRUE,

        is_latest_record = TRUE

    FROM

        account);

增量加载事实表

更新fact_account使用来自的常规快照account,我们将编写另一个SQL脚本到:

  1. 查询account对于数据的当前快照。
  2. 将当前数据与中最近更新的数据进行比较fact_account.
  3. 将行插入fact_account对于自上次快照以来已更改的记录。

您将需要使用以下工具在数据仓库之外保存和调度此SQL脚本,类似dbt Dataform。有关详细信息,请查看Transforming dataETLELT和反向ETL教程的一节。

-- Add the latest snapshot from the account table.

-- This assumes that account is regularly updated from the source system.

INSERT INTO fact_account

SELECT

    *,

    is_first_record = TRUE

FROM

    account

WHERE

    id = id

    AND CURRENT_TIMESTAMP() <> updated_at ();

-- Update the rows from the previous snapshot, if applicable.

WITH previous_snapshot AS (

    SELECT

        id,

        ROW_NUMBER() OVER (PARTITION BY id ORDER BY updated_at DESC) AS row_number

    FROM

        fact_account

    WHERE

        is_first_record = TRUE)

UPDATE

    fact_account fa

SET

    is_latest_record = FALSE

FROM

    previous_snapshot ps

WHERE

    ps.row_number = 2;

用常见用例测试事实表

这是我们所期待的fact_account在它开始填充每日快照之后account:

| id               | country   | type       | status    | updated_at          | is_first_record | is_latest_record |

|------------------|-----------|------------|-----------|---------------------|-----------------|------------------|

| 941bfb1b2fdab087 | Croatia   | Agency     | Active    | 2022-02-04 09:02:09 | TRUE            | FALSE            |

| 941bfb1b2fdab087 | Croatia   | Partner    | Active    | 2022-07-10 14:46:04 | FALSE           | TRUE             |

| dbb64fd5c56e7783 | Singapore | Partner    | Active    | 2022-05-10 02:42:07 | TRUE            | FALSE            |

| dbb64fd5c56e7783 | Singapore | Partner    | Inactive  | 2022-07-14 14:46:04 | FALSE           | TRUE             |

| ced40b3838dd9f07 | Chile     | Advertiser | Test      | 2022-07-02 06:22:34 | TRUE            | TRUE             |

现在,我们可以将事实表放入Metabase,看看它如何回答示例分析问题:

  • 每个月新增多少个账户?
  • 每月有多少客户流失(变为不活跃)?
  • 客户群的流失率是多少?

设置Metabase

如果尚未使用Metabase设置数据库,则可以在几分钟内完成设置:

  1. 下载并安装Metabase,或注册Metabase云免费试用.
  2. 添加数据库用你的事实表。

如果您使用Firebolt遵循本教程,则需要使用用户名和密码登录Firebolt控制台,以及数据库名称(列在控制台主页上)。

  1. Metabase主页的右上角,单击新的>问题.

新帐户

假设我们想知道上个月新增的账户总数。

这种结果适用于自助式用例,例如:

  • “静态数字”可视化.
  • 进度条可视化,根据目标数字衡量上个月的新客户。

人们可以自助使用Metabase过去一个月新增账户等指标查询编辑器使用以下步骤:

  1. 新的>问题.
  2. 选择fact_account作为起始数据。
  3. 选择要查看的度量,选择不同值的数目>ID.
  4. 过滤器按钮,单击是第一个记录然后选择“Is”(默认设置),值为“True”
  5. 过滤器按钮,单击状态选择不是,值为测试
  6. 点击上次更新时间然后选择上个月

或者,它们可以从任何sql编辑器(包括Metabase)中自助提供相同的值SQL编辑器)使用如下代码片段:

SELECT

    COUNT(DISTINCT id) AS new_accounts

FROM

    fact_account

WHERE

    is_first_record = TRUE

    AND status <> "Test"

    AND DATE_TRUNC('month', updated_at) = DATE_TRUNC('month', CURRENT_TIMESTAMP) - INTERVAL '1 MONTH';

客户流失

除了增加到我们业务中的新客户,我们还希望跟踪流失的流失客户。这一次,我们不会把结果局限于上个月的数据,而是会得到这样的月度汇总表:

| report_month | churned_accounts |

|--------------|------------------|

| 2022-05-01   | 23               |

| 2022-06-01   | 21               |

| 2022-07-01   | 16               |

这种结果可以帮助人们自我服务:

  • 柱状图或折线图在客户流失为每一个报告月份.
  • “趋势”可视化以显示客户流失数量的百分比变化,每月一次。
  • 保存的问题或模型可以连接到上的其他表报告月份。这使人们能够使用客户流失列输入其他列的计算在中找不到的fact_account.

人们可以从Metabase月度流失账户汇总表中自助服务查询编辑器通过以下步骤:

  1. 新的>问题.
  2. 选择fact_account作为起始数据。
  3. 选择要查看的度量,选择不同值的数目>ID.
  4. 选择要分组的列,选择更新时间:月.
  5. 单击过滤器按钮。
  6. 点击状态然后选择是的.

他们还可以从任何SQL编辑器(包括MetabaseSQL编辑器)使用如下查询:

SELECT

    DATE_TRUNC('month', updated_at) AS report_month,

    COUNT(DISTINCT id) AS churned_accounts

FROM

    fact_account

WHERE

    status = 'inactive';

高级用例:队列表

队列表是最复杂的用例之一,它可以由设计良好的事实表提供支持。这些数据表测量周转率作为客户年龄的函数,并可用于识别特别成功或不成功的客户组。

我们希望得到这样的结果:

| age | churned_accounts | total_accounts | churn_rate |

|-----|------------------|----------------|------------|

| 1   | 21               | 436            | = 21 / 436 |

| 2   | 26               | 470            | = 26 / 470 |

| 3   | 18               | 506            | = 18 / 506 |

由于这是一个高级用例,我们将重点向您展示fact_account表可以更改为队列表。这些步骤可以在Metabase中通过创建一系列基于另一个的保存的SQL问题来完成。

  1. 创建一个保存的问题first_added_monthchurned_month对于每个帐户:

样品结果

| id               | first_added_month   | churned_month       |

|------------------|---------------------|---------------------|

| 941bfb1b2fdab087 | 2022-02-01          | null                |

| dbb64fd5c56e7783 | 2022-05-01          | 2022-07-01          |

| 67aae9a2e3dccb4b | 2022-07-01          | null                |

SQL代码段

SELECT

     id,

     CASE WHEN is_first_record = TRUE

          THEN DATE_TRUNC('month', updated_at)

          END AS first_added_month,

     CASE WHEN status = 'inactive'

          THEN DATE_TRUNC('month', updated_at)

          ELSE NULL

          END AS churned_month

 FROM

     fact_account;
  1. 将步骤1中保存的问题连接到每月有一行的列中。您可以在SQL中通过生成一个序列(或者可以使用数据仓库中的现有表)来实现这一点。注意月份的连接条件。

样例结果

| id               | first_added_month | churned_month | report_month | age | is_churned |

|------------------|-------------------|---------------|--------------|-----|------------|

| dbb64fd5c56e7783 | 2022-05-01        | 2022-07-01    | 2022-05-01   | 1   | FALSE      |

| dbb64fd5c56e7783 | 2022-05-01        | 2022-07-01    | 2022-06-01   | 2   | FALSE      |

| dbb64fd5c56e7783 | 2022-05-01        | 2022-07-01    | 2022-07-01   | 3   | TRUE       |

SQL代码段

WITH date_series AS (

     SELECT

         *

     FROM

         GENERATE_SERIES('2022-01-01'::date, '2022-12-31'::date, '1 month'::interval) report_month

 )

 SELECT

     *,

     age,

     CASE WHEN s.churned_month = d.report_month

          THEN TRUE ELSE FALSE

          END AS is_churned

 FROM

     step_1 s

     FULL JOIN date_series d

     ON d.report_month >= s.first_added_month

     AND (d.report_month <= s.churned_month

         OR d.report_month <= CURRENT_TIMESTAMP::date);
  1. 步骤2的结果现在可以从查询编辑器聚合到最终结果(您可以使用自定义列计算流失率)。

样例结果

| age | churned_accounts | total_accounts | churn_rate |

|-----|------------------|----------------|------------|

| 1   | 21               | 436            | = 21 / 436 |

| 2   | 26               | 470            | = 26 / 470 |

| 3   | 18               | 506            | = 18 / 506 |

SQL代码段

SELECT

     age,

     COUNT(DISTINCT CASE WHEN is_churned = TRUE

                         THEN id END)  AS churned_accounts,

     COUNT(DISTINCT CASE WHEN is_churned = FALSE

                         THEN id END)  AS total_accounts,

     churned_accounts / total_accounts AS churn_rate

 FROM

     step_2

 GROUP BY

     age;

提高事实表性能

一旦生产中有了一个工作事实表,我们就要注意它是如何扩展的:

  • 该表将使用更多历史记录进行更新。
  • 更多的人开始对表并行运行查询。

假设客户流失逻辑变得非常流行,因此fact_account成为许多下游仪表板和聚合的依赖项(和瓶颈)。

为了提高事实表查询的性能,我们需要根据客户流失计算中最常用的列来预先计算聚合。

SQL数据库中,有几种方法可以做到这一点:

  • 添加索引中最常用的列分组依据声明。
  • 创建视图汇总(预聚合)数据。

在我们的Firebolt数据仓库中,我们可以使用聚合索引。定义聚合索引会告诉Firebolt引擎在SQL查询请求对给定列应用某个聚合时,创建应引用的其他表(在幕后),而不是主事实表。

聚合索引也可以包含在SQL脚本中,用于初始化和加载事实表(但更容易选择正确的在您有机会观察人们在实践中如何使用该表之后的索引)。

下面是一个Firebolt聚合指数的示例,它有助于加快不同报告期内累积和当前流失账户的计数:

CREATE AGGREGATING INDEX IF NOT EXISTS churned_accounts ON fact_account

(

    updated_at,

    DATE_TRUNC('day', updated_at),

    DATE_TRUNC('week', updated_at),

    DATE_TRUNC('month', updated_at),

    DATE_TRUNC('quarter', updated_at),

    COUNT(DISTINCT CASE WHEN status = 'inactive' then id end),

    COUNT(DISTINCT CASE WHEN status = 'inactive' AND is_latest_record = TRUE then id end)

);

Metabase中文社区

你可能感兴趣的:(可视化,Metabase,BI,Metabase,bi,可视化,大数据)