Looker 中的派生表

在 Looker 中,派生表 是一个查询,其结果的使用方式与查询在数据库中的实际表相同。

例如,您可能有一个名为 orders 的数据库表,其中包含许多列。你想计算一些客户级别的汇总指标,例如每个客户下了多少订单,或者每个客户何时下了第一个订单。使用 原生派生表基于 SQL 的派生表,您可以创建一个名为 customer_order_summary 的新数据库表,其中包含这些指标。

然后,您可以像操作数据库中的任何其他表一样操作 customer_order_summary 派生表。

有关派生表的常用用例,请访问 Looker cookbooks: Getting the most out of derived tables in Looker

原生派生表和基于 SQL 的派生表

要在 Looker 项目中创建派生表,请在 view 参数下使用 derived_table 参数。在 derived_table 参数中,您可以通过以下两种方式之一定义派生表的查询:

例如,以下视图文件展示了如何使用 LookML 从 customer_order_summary 派生表创建视图。LookML 的两个版本演示了如何使用 LookML 或 SQL 来定义派生表的查询,从而创建等效的派生表:

  • 原生派生表在 explore_source 参数中使用 LookML 定义查询。在这个示例中,查询基于一个现有的 orders 视图,该视图定义在一个单独的文件中,该文件未在此示例中显示。原生派生表中的 explore_source 查询从 orders 视图文件中引入 customer_idfirst_ordertotal_amount 字段。
  • 基于 SQL 的派生表使用 sql 参数中的 SQL 定义查询。在这个例子中,SQL 查询是对数据库中 orders 表的直接查询。
原生派生表版本
view: customer_order_summary {
  derived_table: {
    explore_source: orders {
      column: customer_id {
        field: orders.customer_id
      }
      column: first_order {
        field: orders.first_order
      }
      column: total_amount {
        field: orders.total_amount
      }
    }
  }
  dimension: customer_id {
    type: number
    primary_key: yes
    sql: ${TABLE}.customer_id ;;
  }
  dimension_group: first_order {
    type: time
    timeframes: [date, week, month]
    sql: ${TABLE}.first_order ;;
  }
  dimension: total_amount {
    type: number
    value_format: "0.00"
    sql: ${TABLE}.total_amount ;;
  }
}
基于 SQL 的派生表版本
view: customer_order_summary {
  derived_table: {
    sql:
      SELECT
        customer_id,
        MIN(DATE(time)) AS first_order,
        SUM(amount) AS total_amount
      FROM
        orders
      GROUP BY
        customer_id ;;
  }
  dimension: customer_id {
    type: number
    primary_key: yes
    sql: ${TABLE}.customer_id ;;
  }
  dimension_group: first_order {
    type: time
    timeframes: [date, week, month]
    sql: ${TABLE}.first_order ;;
  }
  dimension: total_amount {
    type: number
    value_format: "0.00"
    sql: ${TABLE}.total_amount ;;
  }
}

这两个版本都创建了一个名为 customer_order_summary 的视图,该视图基于 orders 表,包含列 customer_idfirst_order,total_amount

除了 derived_table 参数及其子参数之外,此 customer_order_summary 视图的工作方式与任何其他 视图文件 完全相同。无论使用 LookML 还是 SQL 定义派生表的查询,都可以创建基于派生表列的 LookML 度量和维度。

定义好派生表后,就可以像使用数据库中的任何其他表一样使用它。

原生派生表

原生派生表基于您使用 LookML 术语定义的查询。要创建原生派生表,您可以使用 explore_source 参数,该参数位于 view 参数的 derived_table 参数内。您可以通过引用模型中的 LookML 维度或度量来创建原生派生表的列。请参阅本地派生表视图文件。前例

与基于 SQL 的派生表相比,原生派生表在数据建模过程中更容易阅读和理解。

有关创建原生派生表的详细信息,请参阅 创建原生派生表 文档页面。

基于 SQL 的派生表

要创建基于 SQL 的派生表,您需要用 SQL 术语定义查询,并使用 SQL 查询在表中创建列。您不能在基于 SQL 的派生表中引用 LookML 维度和度量。请参阅基于 SQL 的派生表视图文件。前例

最常见的是,您可以使用 sql 参数在 view 参数的 derived_table 参数内定义 SQL 查询。

在 Looker 中创建基于 SQL 的查询的一个实用快捷方法是:使用 SQL Runner 创建 SQL 查询并将其转换为派生表定义

某些特殊情况下不允许使用 sql 参数。在这种情况下,Looker 支持以下参数来定义 持久化派生表 (PDT) 的 SQL 查询:

  • create_process:如果您为 PDT 使用 sql 参数,Looker 会在后台将方言的 CREATE TABLE 数据定义语言 (DDL) 语句封装在您的查询周围,以根据您的 SQL 查询创建 PDT。某些方言不支持在单个步骤中使用 SQL CREATE TABLE 语句。对于这些方言,您无法使用 sql 参数创建 PDT。您可以改为使用 create_process 参数分多步创建 PDT。如需了解相关信息和示例,请参阅 create_process 参数文档页面。
  • sql_create: 如果您的用例需要自定义 DDL 命令,并且您的方言支持 DDL(例如,Google 预测 BigQuery ML),则可以使用 sql_create 参数创建 PDT,而不是使用 sql 参数。有关信息和示例,请参阅 sql_create 文档页面。

无论你使用 sqlcreate_process 还是 sql_create 参数,在所有这些情况下,你都是用 SQL 查询定义派生表,因此它们都被视为基于 SQL 的派生表。

定义基于 SQL 的派生表时,请确保使用 AS 为每一列指定一个清晰的别名。这是因为您需要在维度中引用结果集的列名,例如 ${TABLE}.first_order。这就是为什么前面的例子使用MIN(DATE(time)) AS first_order而不是MIN(DATE(time))

临时派生表和持久派生表

除了原生派生表和基于 SQL 的派生表之间的区别之外,还存在以下区别:暂时的派生表——但不会写入数据库——以及执着的派生表(PDT)——它被写入数据库的模式中。

原生派生表和基于 SQL 的派生表可以是临时的,也可以是持久的。

临时派生表

前面显示的派生表临时派生表的示例。它们是临时的,因为在 derived_table 参数中没有定义 持久性策略

临时派生表不会写入数据库。当用户运行涉及一个或多个派生表的 Explore 查询时,Looker 会使用派生表的 SQL 方言特定组合加上请求的字段、连接和过滤值来构建 SQL 查询。如果之前已经运行过该组合,并且缓存中的结果仍然有效,则 Looker 会使用缓存的结果。有关 Looker 中查询缓存的更多信息,请参阅 缓存查询 文档页面。

否则,如果 Looker 无法使用缓存结果,则每次用户从临时派生表请求数据时,Looker 都必须对数据库运行新查询。因此,您应该确保临时派生表的性能良好,不会给数据库带来过大的压力。如果查询需要一些时间才能运行,则 PDT 通常是更好的选择。

临时派生表支持的数据库方言

要使 Looker 在 Looker 项目中支持派生表,您的数据库方言也必须支持派生表。下表显示了 Looker 最新版本中支持派生表的语言:

点击此处可显示表格。

方言 是否支持?
Actian Avalanche
Amazon Athena
Amazon Aurora MySQL
Amazon Redshift
Amazon Redshift 2.1+
Amazon Redshift Serverless 2.1+
Apache Druid
Apache Druid 0.13.x - 0.17.x
Apache Druid 0.18+
Apache Hive 2.3+
Apache Hive 3.1.2+
Apache Spark 3+
ClickHouse
Cloudera Impala 3.1+
Cloudera Impala 3.1+ with Native Driver
Cloudera Impala with Native Driver
DataVirtuality
Databricks
Denodo 7
Denodo 8 & 9
Dremio
Dremio 11+
Exasol
Google BigQuery Legacy SQL
Google BigQuery Standard SQL
Google Cloud AlloyDB for PostgreSQL
Google Cloud PostgreSQL
Google Cloud SQL
Google Spanner
Greenplum
HyperSQL
IBM Netezza
MariaDB
Microsoft Azure PostgreSQL
Microsoft Azure SQL Database
Microsoft Azure Synapse Analytics
Microsoft SQL Server 2008+
Microsoft SQL Server 2012+
Microsoft SQL Server 2016
Microsoft SQL Server 2017+
MongoBI
MongoSQL
MySQL
MySQL 8.0.12+
Oracle
Oracle ADWC
PostgreSQL 9.5+
PostgreSQL pre-9.5
PrestoDB
PrestoSQL
SAP HANA
SAP HANA 2+
SingleStore
SingleStore 7+
Snowflake
Teradata
Trino
Vector
Vertica

持久化派生表

持久化派生表 (PDT) 是将派生表写入数据库的临时模式,并按照您指定的计划使用 持久化策略 重新生成。

PDT 可以是原生派生表基于 SQL 的派生表

PDT 的要求

要在 Looker 项目中使用持久化派生表 (PDT),您需要以下内容:

  • 支持 PDT 的数据库方言。有关支持 持久化 SQL 派生表持久化原生派生表 的方言列表,请参阅本页后面的 PDT 支持的数据库方言 部分。
  • 数据库的临时架构。这可以是数据库中的任何模式,但我们建议创建一个仅用于此目的的新模式。数据库管理员必须为 Looker 数据库用户配置写入权限。

  • 已配置启用 启用 PDTs 开关的 Looker 连接。此 启用 PDTs 设置通常在您首次设置 Looker 连接时进行配置(有关数据库方言的说明,请参阅 Looker 方言 文档页面),但您也可以在初始设置后为您的连接启用 PDTs。

PDT 支持的数据库方言

要使 Looker 在 Looker 项目中支持 PDT,您的数据库方言也必须支持它们。

为了支持任何类型的 PDT(无论是基于 LookML 的还是基于 SQL 的),方言必须支持写入数据库,除其他要求。有些只读数据库配置不允许持久化工作(最常见的是 Postgres 热交换副本数据库)。在这种情况下,您可以使用 临时派生表 代替。

下表显示了 Looker 最新版本中支持持久化 基于 SQL 的派生表 的方言:

点击此处可显示表格。

方言 是否支持?
Actian Avalanche
Amazon Athena
Amazon Aurora MySQL
Amazon Redshift
Amazon Redshift 2.1+
Amazon Redshift Serverless 2.1+
Apache Druid
Apache Druid 0.13.x - 0.17.x
Apache Druid 0.18+
Apache Hive 2.3+
Apache Hive 3.1.2+
Apache Spark 3+
ClickHouse
Cloudera Impala 3.1+
Cloudera Impala 3.1+ with Native Driver
Cloudera Impala with Native Driver
DataVirtuality
Databricks
Denodo 7
Denodo 8 & 9
Dremio
Dremio 11+
Exasol
Google BigQuery Legacy SQL
Google BigQuery Standard SQL
Google Cloud AlloyDB for PostgreSQL
Google Cloud PostgreSQL
Google Cloud SQL
Google Spanner
Greenplum
HyperSQL
IBM Netezza
MariaDB
Microsoft Azure PostgreSQL
Microsoft Azure SQL Database
Microsoft Azure Synapse Analytics
Microsoft SQL Server 2008+
Microsoft SQL Server 2012+
Microsoft SQL Server 2016
Microsoft SQL Server 2017+
MongoBI
MongoSQL
MySQL
MySQL 8.0.12+
Oracle
Oracle ADWC
PostgreSQL 9.5+
PostgreSQL pre-9.5
PrestoDB
PrestoSQL
SAP HANA
SAP HANA 2+
SingleStore
SingleStore 7+
Snowflake
Teradata
Trino
Vector
Vertica

为了支持持久化的原生派生表(具有基于 LookML 的查询),该方言还必须支持 CREATE TABLE DDL 函数。以下是支持持久模式的方言列表。原生(基于 LookML)派生表在 Looker 的最新版本中:

点击此处可显示表格。

方言 是否支持?
Actian Avalanche
Amazon Athena
Amazon Aurora MySQL
Amazon Redshift
Amazon Redshift 2.1+
Amazon Redshift Serverless 2.1+
Apache Druid
Apache Druid 0.13.x - 0.17.x
Apache Druid 0.18+
Apache Hive 2.3+
Apache Hive 3.1.2+
Apache Spark 3+
ClickHouse
Cloudera Impala 3.1+
Cloudera Impala 3.1+ with Native Driver
Cloudera Impala with Native Driver
DataVirtuality
Databricks
Denodo 7
Denodo 8 & 9
Dremio
Dremio 11+
Exasol
Google BigQuery Legacy SQL
Google BigQuery Standard SQL
Google Cloud AlloyDB for PostgreSQL
Google Cloud PostgreSQL
Google Cloud SQL
Google Spanner
Greenplum
HyperSQL
IBM Netezza
MariaDB
Microsoft Azure PostgreSQL
Microsoft Azure SQL Database
Microsoft Azure Synapse Analytics
Microsoft SQL Server 2008+
Microsoft SQL Server 2012+
Microsoft SQL Server 2016
Microsoft SQL Server 2017+
MongoBI
MongoSQL
MySQL
MySQL 8.0.12+
Oracle
Oracle ADWC
PostgreSQL 9.5+
PostgreSQL pre-9.5
PrestoDB
PrestoSQL
SAP HANA
SAP HANA 2+
SingleStore
SingleStore 7+
Snowflake
Teradata
Trino
Vector
Vertica

逐步构建 PDT

增量式 PDT 是 Looker 通过向表中添加新数据而不是完全重建表来构建的 持久化派生表

如果您的 方言支持增量 PDT,并且您的 PDT 使用基于触发器的持久化策略(datagroup_triggersql_trigger_valueinterval_trigger),您可以 将 PDT 定义为增量 PDT

有关更多信息,请参阅 增量 PDT 文档页面。

增量 PDT 支持的数据库方言

要使 Looker 在 Looker 项目中支持增量 PDT,您的数据库方言也必须支持增量 PDT。下表显示了 Looker 最新版本中支持增量 PDT 的方言:

点击此处可显示表格。

方言 是否支持?
Actian Avalanche
Amazon Athena
Amazon Aurora MySQL
Amazon Redshift
Amazon Redshift 2.1+
Amazon Redshift Serverless 2.1+
Apache Druid
Apache Druid 0.13.x - 0.17.x
Apache Druid 0.18+
Apache Hive 2.3+
Apache Hive 3.1.2+
Apache Spark 3+
ClickHouse
Cloudera Impala 3.1+
Cloudera Impala 3.1+ with Native Driver
Cloudera Impala with Native Driver
DataVirtuality
Databricks
Denodo 7
Denodo 8 & 9
Dremio
Dremio 11+
Exasol
Google BigQuery Legacy SQL
Google BigQuery Standard SQL
Google Cloud AlloyDB for PostgreSQL
Google Cloud PostgreSQL
Google Cloud SQL
Google Spanner
Greenplum
HyperSQL
IBM Netezza
MariaDB
Microsoft Azure PostgreSQL
Microsoft Azure SQL Database
Microsoft Azure Synapse Analytics
Microsoft SQL Server 2008+
Microsoft SQL Server 2012+
Microsoft SQL Server 2016
Microsoft SQL Server 2017+
MongoBI
MongoSQL
MySQL
MySQL 8.0.12+
Oracle
Oracle ADWC
PostgreSQL 9.5+
PostgreSQL pre-9.5
PrestoDB
PrestoSQL
SAP HANA
SAP HANA 2+
SingleStore
SingleStore 7+
Snowflake
Teradata
Trino
Vector
Vertica

创建 PDT

要将派生表转换为持久派生表 (PDT),您需要为该表定义 持久化策略。为了优化性能,您还应该添加 优化策略

持久性策略

派生表的持久性可以由 Looker 管理,或者对于支持物化视图的 方言,可以由数据库使用 物化视图 进行管理。

要使派生表持久化,请将以下参数之一添加到 derived_table 定义中:

使用基于触发器的持久化策略(datagroup_triggersql_trigger_valueinterval_trigger),Looker 会将 PDT 保留在数据库中,直到触发 PDT 进行重建。当 PDT 被触发时,Looker 会重建 PDT 以替换之前的版本。这意味着,有了基于触发器的 PDT,您的用户无需等待 PDT 构建完成即可从 PDT 获取 Explore 查询的答案。

datagroup_trigger

数据组是创建持久化的最灵活方法。如果您定义了一个包含 sql_triggerinterval_triggerdatagroup,则可以使用 datagroup_trigger 参数来启动持久派生表 (PDT) 的重建。

Looker 会将 PDT 保存在数据库中,直到其数据组被触发。当数据组被触发时,Looker 会重建 PDT 以替换之前的版本。这意味着,在大多数情况下,您的用户无需等待 PDT 构建完成。如果用户在 PDT 构建期间请求从中获取数据,但查询结果不在缓存中,则 Looker 将从现有的 PDT 返回数据,直到新的 PDT 构建完成。有关数据组的概述,请参阅 缓存查询

有关再生器如何构建 PDT 的更多信息,请参阅 Looker 再生器 部分。

sql_trigger_value

sql_trigger_value 参数会根据您提供的 SQL 语句触发持久派生表 (PDT) 的重新生成。如果 SQL 语句的结果与先前的值不同,则重新生成 PDT。否则,现有的 PDT 将保留在数据库中。这意味着,在大多数情况下,您的用户无需等待 PDT 构建完成。如果用户在 PDT 构建期间请求从中获取数据,但查询结果不在缓存中,则 Looker 将从现有的 PDT 返回数据,直到新的 PDT 构建完成。

有关再生器如何构建 PDT 的更多信息,请参阅 Looker 再生器 部分。

interval_trigger

interval_trigger 参数会根据您提供的时间间隔(例如 "24 hours""60 minutes")触发持久派生表 (PDT) 的重新生成。与 sql_trigger 参数类似,这意味着通常情况下,当用户查询 PDT 时,PDT 将会预先构建。如果用户在 PDT 构建期间请求从中获取数据,但查询结果不在缓存中,则 Looker 将从现有的 PDT 返回数据,直到新的 PDT 构建完成。

persist_for

另一种选择是使用 persist_for 参数来设置派生表在被标记为过期之前应该存储的时间长度,这样它就不再用于查询,并将从数据库中删除。

当用户首次在其上运行查询时,会构建一个 persist_for 持久派生表 (PDT)。Looker 会将 PDT 在数据库中保留一段时间,该时间长度由 PDT 的 persist_for 参数指定。如果用户在 persist_for 时间内查询 PDT,Looker 会尽可能使用缓存结果,否则在 PDT 上运行查询。

经过 persist_for 时间后,Looker 会从数据库中清除 PDT,下次用户查询时 PDT 将会重建,这意味着查询需要等待重建完成。

使用 persist_for 的 PDT 不会由 Looker regenerator 自动重建,除非存在 PDT 的依赖关系 cascade。当 persist_for 表是具有基于触发器的 PDT(使用 datagroup_triggerinterval_triggersql_trigger_value 持久化策略的 PDT)的依赖级联的一部分时,重建器将监视并重建 persist_for 表,以便重建级联中的其他表。参见Looker 如何构建级联派生表本页的这一部分。

materialized_view: yes

物化视图允许您使用数据库的功能在 Looker 项目中持久化派生表。如果您的数据库方言 支持物化视图,并且您的 Looker 连接 配置了启用 启用 PDT 开关,则您可以通过为派生表指定 materialized_view: yes 来创建具体化视图。物化视图支持 原生派生表基于 SQL 的派生表

持久派生表 (PDT) 类似,具体化视图是将查询结果存储为数据库暂存模式中的表。PDT 和具体化视图的主要区别在于表的刷新方式:

  • 对于 PDT,持久化策略在 Looker 中定义,持久化由 Looker 管理。
  • 对于物化视图,数据库负责维护和刷新表中的数据。

因此,具体化视图功能需要您对您的方言及其特性有深入的了解。大多数情况下,每当数据库检测到具体化视图查询的表中有新数据时,数据库都会刷新具体化视图。物化视图最适合需要实时数据的场景。

有关方言支持、要求和重要注意事项的信息,请参阅 materialized_view 参数文档页面。

优化策略

由于持久化派生表 (PDT) 存储在数据库中,因此您应该使用以下策略来优化 PDT,这些策略由您的数据库方言支持:

例如,要为 派生表 example 添加持久性,您可以将其设置为在数据组 orders_datagroup 触发时重建,并在 customer_idfirst_order 上添加索引,如下所示:

view: customer_order_summary {
  derived_table: {
    explore_source: orders {
      ...
    }
    datagroup_trigger: orders_datagroup
    indexes: ["customer_id", "first_order"]
  }
}

如果您不添加索引(或您的方言的等效索引),Looker 将警告您应该这样做以提高查询性能。

PDT 的应用案例

持久化派生表 (PDT) 非常有用,因为它们可以将查询结果持久化到表中,从而提高查询性能。

一般而言,最佳实践是,开发者应尽量避免使用 PDT 来建模数据,除非绝对必要。

在某些情况下,可以通过其他方式优化数据。例如,添加索引或更改列的数据类型可能无需创建 PDT 即可解决问题。务必使用 SQL Runner 工具的 Explain 功能分析慢查询的执行计划

除了减少频繁运行查询的查询时间和数据库负载外,PDT 还有其他几个用途,包括:

你也可以使用 PDT 定义主键在没有合理方法将表中的唯一行标识为主键的情况下。

使用 PDT 测试优化方案

您可以使用 PDT 来测试不同的索引、分布和其他优化选项,而无需 DBA 或 ETL 开发者的大量支持。

假设你有一个表,但你想测试不同的索引。该视图的初始 LookML 代码可能如下所示:

view: customer {
  sql_table_name: warehouse.customer ;;
}

要测试优化策略,可以使用 indexes 参数向 LookML 添加索引,如下所示:

view: customer {
  # sql_table_name: warehouse.customer
  derived_table: {
    sql: SELECT * FROM warehouse.customer ;;
    persist_for: "8 hours"
    indexes: [customer_id, customer_name, salesperson_id]
  }
}

查询视图一次即可生成 PDT。然后运行测试查询并比较结果。如果结果令人满意,您可以要求 DBA 或 ETL 团队将索引添加到原始表中。

请记得将视图代码改回原样,移除 PDT。

使用 PDT 进行预连接或聚合数据

对于大容量数据或多种数据类型,预先连接或预先聚合数据有助于调整查询优化。

例如,假设您想根据客户首次下单的时间,按客户群组创建一个查询。如果每次需要实时数据时都多次运行此查询,则成本可能很高;但是,您可以使用 PDT 仅计算一次查询,然后重用结果:

view: customer_order_facts {
  derived_table: {
    sql: SELECT
    c.customer_id,
    MIN(o.order_date) OVER (PARTITION BY c.customer_id) AS first_order_date,
    MAX(o.order_date) OVER (PARTITION BY c.customer_id) AS most_recent_order_date,
    COUNT(o.order_id) OVER (PARTITION BY c.customer_id) AS lifetime_orders,
    SUM(o.order_value) OVER (PARTITION BY c.customer_id) AS lifetime_value,
    RANK() OVER (PARTITION BY c.customer_id ORDER BY o.order_date ASC) AS order_sequence,
    o.order_id
    FROM warehouse.customer c LEFT JOIN warehouse.order o ON c.customer_id = o.customer_id
    ;;
    sql_trigger_value: SELECT CURRENT_DATE ;;
    indexes: [customer_id, order_id, order_sequence, first_order_date]
  }
}

级联派生表

您可以在一个派生表的定义中引用另一个派生表,从而创建级联派生表级联永久性派生表 (PDT)(具体取决于情况)链。级联派生表的示例:表 TABLE_D 依赖于另一个表 TABLE_C,而 TABLE_C 依赖于 TABLE_BTABLE_B 依赖于 TABLE_A

引用派生表的语法

如需在另一个派生表中引用派生表,请使用以下语法:

`${derived_table_or_view_name.SQL_TABLE_NAME}`

在此格式中,SQL_TABLE_NAME 是一个字面量字符串。例如,您可以使用以下语法引用 clean_events 派生表:

`${clean_events.SQL_TABLE_NAME}`

您可以使用相同的语法来引用 LookML 视图。同样,在这种情况下,SQL_TABLE_NAME 是一个字面量字符串。

在下一个示例中,系统会根据数据库中的 events 表创建 clean_events PDT。clean_events PDT 会从 events 数据库表中排除不需要的行。然后,系统会显示第二个 PDT;event_summary PDT 是 clean_events PDT 的摘要。每当向 clean_events 添加新行时,event_summary 表都会重新生成。

event_summary PDT 和 clean_events PDT 是级联 PDT,其中 event_summary 依赖于 clean_events(因为 event_summary 是使用 clean_events PDT 定义的)。在此特定示例中,可以在单个 PDT 中更高效地完成此操作,但它有助于演示派生表的引用。

view: clean_events {
  derived_table: {
    sql:
      SELECT *
      FROM events
      WHERE type NOT IN ('test', 'staff') ;;
    datagroup_trigger: events_datagroup
  }
}

view: events_summary {
  derived_table: {
    sql:
      SELECT
        type,
        date,
        COUNT(*) AS num_events
      FROM
        ${clean_events.SQL_TABLE_NAME} AS clean_events
      GROUP BY
        type,
        date ;;
    datagroup_trigger: events_datagroup
  }
}

虽然并非总是必需,但以这种方式引用派生表时,通常最好使用以下格式为该表创建别名:

${derived_table_or_view_name.SQL_TABLE_NAME} AS derived_table_or_view_name

上一个示例执行以下操作:

${clean_events.SQL_TABLE_NAME} AS clean_events

使用别名很有帮助,因为在后台,PDT 在数据库中是用冗长的代码命名的。在某些情况下(尤其是使用 ON 子句时),可能会忘记需要使用 ${derived_table_or_view_name.SQL_TABLE_NAME} 语法来检索这个冗长的名称。使用别名可以帮助避免这类错误。

Looker 如何构建级联派生表

对于级联 临时 派生表,如果用户的查询结果不在缓存中,Looker 将构建查询所需的所有派生表。如果你有一个TABLE_D定义包含引用TABLE_C, 然后TABLE_D依赖TABLE_C。这意味着,如果您查询 TABLE_D 并且该查询不在 Looker 的缓存中,Looker 将重建 TABLE_D。但首先,它必须重建 TABLE_C

考虑一个包含级联临时派生表的场景,其中TABLE_D取决于TABLE_C这取决于TABLE_B这取决于TABLE_A。如果 Looker 在缓存中没有针对 TABLE_C 的查询的有效结果,Looker 将构建查询所需的所有表。所以 Looker 会先构建 TABLE_A,然后构建 TABLE_B,最后构建 TABLE_C

在这种情况下,TABLE_A 必须先生成完毕,Looker 才能开始生成 TABLE_BTABLE_B 必须先生成完毕,Looker 才能开始生成 TABLE_C。当 TABLE_C 完成后,Looker 将提供查询结果。(由于不需要 TABLE_D 来回答此查询,Looker 目前不会重建 TABLE_D。)

有关使用同一数据组的级联 PDT 的示例场景,请参阅 datagroup 参数文档页面。

对于 PDT,基本逻辑也相同:Looker 将构建回答查询所需的任何表,一直向上追溯依赖关系链。但对于 PDT 来说,通常情况下,表已经存在,不需要重建。对于级联 PDT 的标准用户查询,Looker 仅在数据库中没有有效版本的 PDT 时才会重建级联中的 PDT。如果您想强制级联中所有 PDT 重建,您可以手动重建查询表通过探索。

需要理解的一个重要逻辑点是,在 PDT 级联的情况下,依赖的 PDT 本质上是 查询 它所依赖的 PDT。对于使用 persist_for 策略的 PDT 来说,这一点尤为重要。通常,persist_for PDT 会在用户查询时构建,在数据库中保留到 persist_for 时间间隔结束,然后直到用户下次查询时才会重新构建。不过,如果 persist_for PDT 属于包含基于触发器的 PDT(使用 datagroup_triggerinterval_triggersql_trigger_value 持久性策略的 PDT)的级联,则每当重建其依赖的 PDT 时,系统都会查询 persist_for PDT。因此,在这种情况下,系统会按照所依赖的 PDT 的时间表重建 persist_for。这意味着,persist_for PDT 可能会受到其依赖项的持久性策略的影响。

为深度嵌套的 PDT 结构(具有多级依赖关系的级联 PDT 链)配置持久性时,请确保缓存保留期和数据组间隔能够为整个级联提供足够的构建时间。较短的缓存保留期限可能会导致竞态条件,从而在刷新期间导致 409 Conflict 错误。如需了解详情和推荐的最佳实践,请参阅本页面上的排查深度嵌套 PDT 中的 409 Conflict 错误部分。

手动为查询重建永久性表

用户可以在“探索”菜单中选择重新构建派生表并运行选项,以替换持久性设置并重新构建“探索”中当前查询所需的所有永久性派生表 (PDT) 和汇总表

点击“探索操作”按钮会打开“探索”菜单,您可以在其中选择“重新构建派生表并运行”。

此选项仅对拥有 develop 权限的用户显示,并且仅在探索查询加载完毕后显示。

重建派生表并运行选项会重建回答查询所需的所有持久表(所有 PDT 和聚合表),而不管它们的持久化策略是什么。这包括当前查询中的所有汇总表和 PDT,还包括当前查询中的汇总表和 PDT 所引用的所有汇总表和 PDT。

对于增量 PDT,“重新构建派生表并运行”选项会触发新增量的构建。对于增量 PDT,增量包括 increment_key 参数中指定的时间段,以及 increment_offset 参数中指定的之前的时间段数(如有)。如需查看一些示例场景,了解增量 PDT 如何根据其配置进行构建,请参阅增量 PDT 文档页面。

对于级联 PDT,这意味着重建级联中的所有派生表,从顶部开始。这与您在临时派生表的级联中查询表时的行为相同:

如果 table_c 依赖于 table_b,而 table_b 依赖于 table_a,那么重建 table_c 时会先重建 table_a,然后重建 table_b,最后重建 table_c。

请注意以下有关手动重建派生表的事项:

  • 对于发起 重建派生表并运行 操作的用户,查询将等待表重建完成,然后再加载结果。其他用户的查询仍将使用现有表。持久表重建完成后,所有用户都将使用重建后的表。虽然此过程旨在避免在重建表时中断其他用户的查询,但这些用户仍然可能会受到数据库额外负载的影响。如果在营业时间内触发重建操作可能会给数据库带来无法接受的压力,则可能需要告知用户,他们绝不应该在这些时间段内重建某些 PDT 或聚合表。
  • 如果用户处于 开发模式,并且 Explore 基于 开发表,则 重建派生表并运行 操作将为 Explore 重建开发表,而不是生产表。但是,如果开发模式下的 Explore 使用的是派生表的生产版本,则会重建生产表。有关开发表和生产表的信息,请参阅开发模式下的持久化表

  • 对于 Looker 托管的实例,如果派生表重建时间超过一小时,则表将无法成功重建,浏览器会话将超时。有关可能影响 Looker 进程的超时的更多信息,请参阅 管理设置 - 查询 文档页面上的 查询超时和排队 部分。

开发模式下的持久化表

Looker 在 开发模式 下对管理持久化表有一些特殊行为。

如果在开发模式下查询持久化表没有如果对该表的定义进行任何更改,Looker 将查询该表的生产版本。如果你如果对表定义进行更改,影响到表中的数据或表的查询方式,则下次在开发模式下查询表时,将创建一个新的表开发版本。有了这样的开发表,你就可以在不打扰用户的情况下测试更改。

是什么促使 Looker 创建开发表

无论是否处于开发模式,Looker 都会尽可能使用现有的生产表来回答查询。但在某些情况下,Looker 无法在开发模式下使用生产表进行查询:

  • 如果您的持久化表有一个参数,将其数据集缩小到 在开发模式下工作速度更快
  • 如果您对持久化表的定义进行了更改,从而影响了表中的数据,

如果您处于开发模式并查询,Looker 将创建一个开发表。基于 SQL 的派生表这是用以下方式定义的条件WHERE条款if prodif dev声明

对于在开发模式下没有用于缩小数据集范围的参数的持久化表,除非您更改表的定义,否则 Looker 会使用该表的生产版本来回答开发模式下的查询。然后在开发模式下查询该表。这适用于对表格进行的任何更改,这些更改会影响表格中的数据或表格的查询方式。

以下是一些会触发 Looker 创建持久表开发版本的更改示例(只有在您进行这些更改后查询该表时,Looker 才会创建该表):

对于不修改表数据或不影响 Looker 查询表的方式的更改,Looker 不会创建开发表。publish_as_db_view 参数就是一个很好的例子:在开发模式下,如果您只更改派生表的 publish_as_db_view 设置,Looker 不需要重建派生表,因此不会创建开发表。

Looker 会保留开发表多长时间?

无论表的实际持久化策略如何,Looker 都将开发持久化表视为具有 持久化策略persist_for: "24 hours"。Looker 这样做是为了确保开发表不会保留超过一天,因为 Looker 开发者在开发过程中可能会查询表的多个迭代版本,并且每次构建新的开发表时都会进行查询。为了防止开发表使数据库变得混乱,Looker 应用了 persist_for: "24 hours" 策略,以确保这些表经常从数据库中清理。

否则,Looker 在开发模式下构建持久化派生表 (PDT) 和聚合表的方式与在生产模式下构建持久化表的方式相同。

如果在向 PDT 或聚合表部署更改时,开发表已持久化到数据库中,则 Looker 通常可以使用开发表作为生产表,这样用户在查询表时就不必等待表构建完成。

请注意,部署更改后,根据具体情况,可能仍需要重建表才能在生产环境中查询:

  • 如果距离您在开发模式下查询该表已经超过 24 小时,则该表的开发版本将被标记为已过期,并且不会再用于查询。您可以检查未构建的 PDT。通过使用 Looker IDE或通过使用发展标签页持久化派生表。如果您有未构建的 PDT,可以在进行更改之前在开发模式下查询它们,以便开发表可在生产环境中使用。
  • 如果持久化表具有 dev_filters 参数(对于 原生派生表)或使用 if prodif dev 语句的 条件 WHERE 子句(对于 基于 SQL 的派生表),则开发表不能用作生产版本,因为开发版本具有缩减的数据集。如果是这种情况,在完成表的开发之后,在部署更改之前,您可以注释掉 dev_filters 参数或条件 WHERE 子句,然后在开发模式下查询表。Looker 将构建一个完整的表格版本,当您部署更改时,该表格可用于生产环境。

否则,如果您在没有可用作生产表的有效开发表时部署更改,则 Looker 将在下次以生产模式查询该表时(对于使用 persist_for 策略的持久化表)或下次运行 regenerator 时(对于使用 datagroup_triggerinterval_triggersql_trigger_value 的持久化表)重建该表。

检查开发模式下未构建的 PDT

如果在将更改部署到持久派生表 (PDT) 或聚合表时,开发表已持久化到数据库中,则 Looker 通常可以将开发表用作生产表,这样用户在查询表时就不必等待表构建完成。有关更多详细信息,请参阅此页面上的 Looker 保留开发表的时间什么促使 Looker 创建开发表 部分。

因此,最好在部署到生产环境时构建所有 PDT,以便这些表可以立即用作生产版本。

您可以在项目中检查是否存在未构建的 PDT。项目健康控制板。在 Looker IDE 中单击 项目健康状况 图标,打开 项目健康状况 面板。然后单击“验证 PDT 状态”按钮。

如果存在未构建的 PDT,项目健康状况面板将列出它们:

项目健康状况面板会显示项目的未构建 PDT 列表以及“转到 PDT 管理”按钮。

如果您拥有 see_pdts 权限,您可以点击 前往 PDT 管理 按钮。Looker 将打开 持久派生表 页面 的 开发 选项卡,并将结果过滤到您特定的 LookML 项目。从那里,您可以查看哪些开发 PDT 已构建和未构建,以及访问其他故障排除信息。有关更多信息,请参阅 Admin 设置 - 持久派生表 文档页面。

一旦您在项目中识别出未构建的 PDT,您可以通过打开查询该表的 Explore,然后使用 Explore 菜单中的 重建派生表并运行 选项来构建其开发版本。参见手动重建查询的持久表本页的这一部分。

餐桌共享和清理

在任何给定的 Looker 实例中,如果表具有相同的定义和相同的持久化方法设置,Looker 将在用户之间共享持久化表。此外,如果表的定义不再存在,Looker 会将该表标记为已过期。

这样做有几个好处:

  • 如果在开发模式下没有对表进行任何更改,则查询将使用现有的生产表。除非你的桌子是…,否则情况就是如此。基于 SQL 的派生表这是用以下方式定义的条件WHERE条款if prodif dev声明。如果表定义了条件 WHERE 子句,则在开发模式下查询表时,Looker 将构建一个开发表。(对于带有 dev_filters 参数的 原生派生表,Looker 具有在开发模式下使用生产表来回答查询的逻辑,除非您更改表的定义,然后在开发模式下查询该表。)
  • 如果两个开发者在开发模式下对同一个表进行了相同的更改,他们将共享同一个开发表。
  • 一旦您将更改从开发模式推送到生产模式,旧的生产定义将不再存在,因此旧的生产表将被标记为过期并删除。
  • 如果您决定放弃开发模式的更改,则该表定义将不再存在,因此不需要的开发表将被标记为过期并删除。

在开发模式下工作速度更快

有些情况下,您创建的持久派生表 (PDT) 需要很长时间才能生成,如果您在开发模式下测试大量更改,这可能会非常耗时。对于这些情况,您可以在开发模式下提示 Looker 创建派生表的较小版本。

对于 原生派生表,您可以使用 explore_sourcedev_filters 子参数来指定仅应用于派生表开发版本的过滤器:

view: e_faa_pdt {
  derived_table: {
  ...
    datagroup_trigger: e_faa_shared_datagroup
    explore_source: flights {
      dev_filters: [flights.event_date: "90 days"]
      filters: [flights.event_date: "2 years", flights.airport_name: "Yucca Valley Airport"]
      column: id {}
      column: airport_name {}
      column: event_date {}
    }
  }
...
}

此示例包含一个 dev_filters 参数,用于过滤过去 90 天的数据;以及一个 filters 参数,用于过滤过去 2 年的数据以及尤卡谷机场的数据。

dev_filters 参数与 filters 参数配合使用,以便所有过滤器都应用于表的开发版本。如果 dev_filtersfilters 都为同一列指定了过滤条件,则 dev_filters 在表的开发版本中优先。在这个例子中,表格的开发版本会将尤卡谷机场的数据过滤为最近 90 天的数据。

为了基于 SQL 的派生表Looker 支持条件WHERE包含不同生产选项的条款(if prod )和发展(if dev表格的多个版本:

view: my_view {
  derived_table: {
    sql:
      SELECT
        columns
      FROM
        my_table
      WHERE
        -- if prod -- date > '2000-01-01'
        -- if dev -- date > '2020-01-01'
      ;;
  }
}

在这个例子中,当处于生产模式时,查询将包含 2000 年及以后的所有数据;而当处于开发模式时,查询将只包含 2020 年及以后的数据。策略性地使用此功能来限制结果集并提高查询速度,可以使开发模式下的更改更容易验证。

Looker 如何构建 PDT

在定义持久化派生表 (PDT) 之后,无论是首次运行还是由 regenerator 触发以根据其 持久化策略 重建,Looker 都将执行以下步骤:

  1. 使用派生表 SQL 构造 CREATE TABLE AS SELECT (或 CTAS) 语句并执行它。例如,要重建名为 customer_orders_facts 的 PDT:CREATE TABLE tmp.customer_orders_facts AS SELECT ... FROM ... WHERE ...
  2. 在表构建时发出创建索引的语句
  3. 将表名从 LC$..(“Looker 创建”)重命名为 LR$..(“Looker 读取”),以表明该表已准备好使用。
  4. 删除任何不再使用的旧版本表格。

这其中蕴含着几个重要的意义:

  • 生成派生表的 SQL 语句必须在 CTAS 语句中有效。
  • SELECT 语句结果集中的列别名必须是有效的列名。
  • 指定分布、排序键和索引时使用的名称必须是派生表的 SQL 定义中列出的列名,而不是 LookML 中定义的字段名。

观察者再生器

Looker 重建器检查状态并启动触发器持久化表的重建。触发器持久化表是一种持久化派生表 (PDT) 或聚合表它使用触发器作为持久化策略:

  • 对于使用 sql_trigger_value 的表,触发器是在表的 sql_trigger_value 参数中指定的查询。当最新触发查询检查的结果与上一次触发查询检查的结果不同时,Looker 重建器会触发表的重建。例如,如果您的派生表使用 SQL 查询 SELECT CURDATE() 进行持久化,则 Looker 重生成器将在日期更改后下次检查触发器时重建该表。
  • 对于使用 interval_trigger 的表,触发器是在表的 interval_trigger 参数中指定的持续时间。Looker 重建器会在指定时间过后触发表的重建。
  • 对于使用 datagroup_trigger 的表,触发器可以是关联数据组的 sql_trigger 参数中指定的查询,也可以是数据组的 interval_trigger 参数中指定的时间段。

Looker 重生成器还会为使用 persist_for 参数的持久化表启动重建,但仅当 persist_for 表是触发器持久化表的依赖项 cascade 时才会如此。在这种情况下,Looker 重建器将启动 persist_for 表的重建,因为级联重建中需要该表来重建其他表。否则,重新生成程序将不会监视使用 persist_for 策略的持久化表。

此外,如果您使用 derived_analytic_model 参数定义了分析模型,Looker 重新生成器会在您的数据库中创建 分析模型。Looker 再生器处理派生分析模型,类似于 PDT,即 物化视图。物化视图和派生分析模型都只创建一次,并且不支持触发器,例如 数据组触发器SQL 触发器间隔触发器。Looker 重生成程序仅在 LookML 定义更改或其依赖的任何 LookML 视图更改时才在数据库中重新创建分析模型。

Looker 重新生成周期按 Looker 管理员在数据库连接的 维护计划 设置中配置的固定间隔开始(默认间隔为五分钟)。但是,Looker 再生器只有在完成上一个周期的所有检查和 PDT 重建后才会开始新的周期。这意味着,如果您有长时间运行的 PDT 构建,Looker 重新生成周期可能不会像 维护计划 设置中定义的那样频繁运行。其他因素也会影响重建表所需的时间,详情请参见下文。实现持久表的重要考虑因素本页的这一部分。

如果 PDT 构建失败,则再生器可能会在下一个再生器周期中尝试重建该表:

  • 如果数据库连接上启用了 重试失败的 PDT 构建 设置,即使表的触发条件未满足,Looker 重建器也会在下一个重建周期中尝试重建表。
  • 如果禁用 重试失败的 PDT 构建 设置,则 Looker 重新生成程序不会尝试重建表,直到满足 PDT 的触发条件。

如果用户在持久化表构建过程中请求该表的数据,而查询结果不在缓存中,Looker 会检查现有表是否仍然有效。(如果旧表与新表版本不兼容,则旧表可能无效。这种情况可能发生在新表具有不同的定义、新表使用不同的数据库连接,或者新表是使用不同版本的 Looker 创建的。) 如果现有表仍然有效,Looker 将从现有表中返回数据,直到新表构建完成。否则,如果现有表无效,Looker 将在新表重建后提供查询结果。

实现持久表的重要考虑因素

考虑到持久化表(PDT 和 聚合表)的实用性,可以在 Looker 实例上积累很多这样的表。有可能出现这样的场景:Looker 重生成器 需要同时构建多个表。尤其是级联表对于长时间运行的表,您可以创建一个场景,其中表在重建之前会有很长的延迟,或者当数据库努力生成表时,用户在从表中获取查询结果时会遇到延迟。

Looker regenerator 检查 PDT 触发器,以确定是否应该重建触发器持久化的表。再生周期是按 Looker 管理员在数据库连接的 维护计划 设置中配置的固定间隔设置的(默认间隔为五分钟)。

重建表格所需的时间会受到多种因素的影响:

  • 您的 Looker 管理员可能已通过数据库连接上的 维护计划 设置更改了重新生成触发器检查的间隔。
  • Looker 再生器只有在完成上一个周期的所有检查和 PDT 重建后才会开始新的周期。因此,如果您有长时间运行的 PDT 构建,Looker 重新生成周期可能不会像 维护计划 设置那样频繁。
  • 默认情况下,重建器可以通过连接一次启动一个 PDT 或聚合表的重建。Looker 管理员可以通过在连接设置中使用 PDT 构建器连接的最大数量 字段来调整重新生成器允许的并发重建数量。
  • 由同一 datagroup 触发的所有 PDT 和聚合表将在同一重生成过程中重建。如果有很多表直接或由于 级联依赖 而使用数据组,这可能会造成沉重的负担。

除了前面提到的注意事项之外,在某些情况下,您也应该避免向派生表添加持久化功能:

  • 当派生表被 扩展 时 — PDT 的每次扩展都会在您的数据库中创建一个新的表副本。
  • 当派生表使用 模板过滤器或 Liquid 参数 时 — 使用模板过滤器或 Liquid 参数的派生表不支持持久化。
  • 当使用 用户属性access_filterssql_always_where 从 Explore 构建 原生派生表 时 — 将在您的数据库中为指定的每个可能的用户属性值构建表的副本。
  • 当底层数据频繁更改且您的数据库方言不支持 增量 PDT 时。
  • 当创建 PDT 的成本和时间过高时。

根据 Looker 连接中持久化表的数量和复杂程度,队列可能包含许多需要在每个周期检查和重建的持久化表,因此在 Looker 实例上实现派生表时,务必牢记这些因素。

使用 API 大规模管理 PDT

随着实例上创建的 PDT 越来越多,监控和管理按不同计划刷新的持久派生表 (PDT) 变得越来越复杂。考虑使用 Looker Apache Airflow 集成 来管理您的 PDT 计划以及其他 ETL 和 ELT 流程。

监测和故障排除 PDT

如果您使用持久化派生表 (PDT),尤其是级联对于 PDT 来说,查看您的 PDT 状态是有帮助的。您可以使用 Looker 持久派生表 管理页面 查看您的 PDT 的状态。您还可以查看 PDT 故障排除树 以进行逐步调试。

尝试对 PDT 进行故障排除时:

  • 在调查 PDT 事件日志 时,请特别注意 开发表 和生产表之间的区别。
  • 请确认 Looker 连接中的 Temp Database 设置与您的实际临时架构或数据库匹配。如果连接上的 Temp Database 设置与数据库中的临时架构不匹配,请更新 Temp Database 设置,以便 Looker 可以将持久派生表存储在数据库中。
  • 确定是所有 PDT 都存在问题,还是只有一台 PDT 存在问题。如果其中一个出现问题,则该问题很可能是由 LookML 或 SQL 错误引起的。
  • 确定 PDT 出现问题的时间是否与计划重建的时间相吻合。
  • 确保所有 sql_trigger_value 查询都能成功执行,并且只返回一行和一列。对于基于 SQL 的 PDT,您可以通过在 SQL Runner 中运行它们来执行此操作。(应用 LIMIT 可以防止失控查询。) 有关使用 SQL Runner 调试派生表的更多信息,请参阅 使用 sql runner 测试派生表 社区帖子。
  • 对于基于 SQL 的 PDT,请使用 SQL Runner 验证 PDT 的 SQL 是否执行无误。(请务必在 SQL Runner 中应用 LIMIT 以保持查询时间合理。)
  • 对于基于 SQL 的派生表,避免使用 公共表表达式 (CTE)。将 CTE 与 DT 结合使用会创建嵌套的 WITH 语句,这可能会导致 PDT 在没有警告的情况下失败。相反,请使用 CTE 的 SQL 创建一个辅助 DT,并使用 ${derived_table_or_view_name.SQL_TABLE_NAME} 语法从第一个 DT 引用该 DT。
  • 检查问题 PDT 所依赖的任何表(无论是普通表还是 PDT 本身)是否存在且可以查询。
  • 确保问题 PDT 所依赖的任何表都没有共享锁或排他锁。Looker 要成功构建 PDT,需要获取要更新的表的独占锁。这将与其他正在讨论中的共享锁或独占锁发生冲突。在所有其他锁定解除之前,Looker 将无法更新 PDT。对于 Looker 正在构建 PDT 的表上的任何独占锁,情况也是如此;如果表上有独占锁,则 Looker 将无法获取共享锁来运行查询,直到独占锁被清除。
  • 在 SQL Runner 中使用 显示进程 按钮。如果大量进程处于活动状态,则可能会减慢查询速度。
  • 监控查询中的评论。请参阅此页面上的 PDT 查询注释 部分。
  • 当在派生表的 SQL 查询中使用数据库特定的日期函数(例如 current_date())时,用户的 Looker 会话和底层数据库之间可能存在时区不匹配的风险。由于数据库函数直接在数据库中执行,不会经过 Looker 的查询时区转换,因此这种差异可能会导致意外的日期过滤结果(例如,“昨天”的日期过滤结果可能是两天前的午夜)。

    要解决此问题,请确保数据库和 Looker 实例之间的时区正确对齐,这可能需要与您的数据工程团队协调。

  • 如果在深度嵌套的 PDT 结构(具有多级依赖关系的级联 PDT 链)中刷新 PDT 时遇到 409 Conflict 错误,请参阅本页上的 深度嵌套 PDT 中的 409 冲突错误故障排除 部分。

PDT 的查询评论

数据库管理员可以区分普通查询和生成持久派生表 (PDT) 的查询。Looker 会向 CREATE TABLE ... AS SELECT ... 语句添加注释,其中包含 PDT 的 LookML 模型和视图,以及 Looker 实例的唯一标识符(slug)。如果 PDT 是以开发模式下的用户的名义生成的,则注释将显示用户的 ID。PDT 生成评论遵循以下模式:

-- Building `<view_name>` in dev mode for user `<user_id>` on instance `<instance_slug>`
CREATE TABLE `<table_name>` SELECT ...
-- finished `<view_name>` => `<table_name>`

如果 Looker 必须为 Explore 的查询生成 PDT,则 PDT 生成注释将显示在 Explore 的 SQL 选项卡中。注释将显示在 SQL 语句的顶部。

最后,PDT 生成注释会出现在 查询 管理页面上每个查询的 查询详情 弹出窗口信息 选项卡的 消息 字段中。

故障后重建 PDT

当持久化派生表 (PDT) 发生故障时,查询该 PDT 时会发生以下情况:

  • 如果之前运行过相同的查询,Looker 将使用缓存中的结果。(参见)缓存查询(请参阅文档页面了解其工作原理。)
  • 如果缓存中没有结果,Looker 将从数据库中的 PDT 中提取结果(如果存在有效的 PDT 版本)。
  • 如果数据库中没有有效的 PDT,Looker 将尝试重建 PDT。
  • 如果无法重建 PDT,Looker 将为查询返回错误。Looker 重生成器 将在下次查询 PDT 或下次 PDT 的持久化策略触发重建时尝试重建 PDT。

对于级联的级联 PDT,逻辑相同,只是级联 PDT 的情况有所不同:

  • 如果一个表的构建失败,则会导致依赖链中所有 PDT 的构建失败。
  • 依赖的 PDT 本质上是在查询它所依赖的 PDT,因此一个表的持久化策略可以触发沿链向上 个 PDT 的重建。

回顾之前的例子级联表, 在哪里TABLE_D取决于TABLE_C这取决于TABLE_B这取决于TABLE_A

如果 TABLE_B 发生故障,则所有标准(非级联)行为均适用于 TABLE_B

  1. 如果查询 TABLE_B,Looker 首先尝试使用缓存返回结果。
  2. 如果此尝试失败,Looker 接下来会尝试使用表格的先前版本(如果可能)。
  3. 如果这次尝试也失败了,Looker 会尝试重建表。
  4. 最后,如果 TABLE_B 无法重建,Looker 将返回错误。

Looker 将在下次查询表或表的持久化策略下次触发重建时再次尝试重建 TABLE_B

这也适用于 TABLE_B 的受抚养人。因此,如果 TABLE_B 无法构建,并且对 TABLE_C 有查询,则会发生以下序列:

  1. Looker 将尝试使用 TABLE_C 上的查询缓存。
  2. 如果缓存中没有结果,Looker 将尝试从数据库 TABLE_C 中获取结果。
  3. 如果没有有效的 TABLE_C 版本,Looker 将尝试重建 TABLE_C,这将在 TABLE_B 上创建一个查询。
  4. Looker 将尝试重建 TABLE_B(如果 TABLE_B 没有被修复,则会失败)。
  5. 如果 TABLE_B 无法重建,则 TABLE_C 也无法重建,因此 Looker 将对 TABLE_C 的查询返回错误。
  6. Looker 随后会尝试重建TABLE_C根据其通常的持久化策略,或者下次查询 PDT 时(包括下次查询 PDT 时)。TABLE_D尝试构建,因为TABLE_D取决于TABLE_C)。

一旦您解决了 TABLE_B 的问题,那么 TABLE_B 和每个依赖表将根据其持久性策略尝试重建,或者在下次查询时(包括下次依赖 PDT 尝试重建时)重建。或者,如果级联中的 PDT 的开发版本是在开发模式下构建的,则开发版本可以用作新的生产 PDT。(参见)开发模式下的持久化表本页的相应章节将介绍其工作原理。) 或者,您可以使用 Explore 对 TABLE_D 运行查询,然后 手动重建查询的 PDT,这将强制重建依赖级联中所有向上延伸的 PDT。

排查深度嵌套 PDT 中的 409 冲突错误

当您处理深度嵌套的 PDT 结构(具有多个依赖级别的级联 PDT 链)时,配置较短的缓存保留期(例如 15 分钟)可能会导致竞态条件,从而在刷新期间产生 409 Conflict 错误。

出现这种竞态条件的原因是,当上层 PDT 仍在构建过程中时,下层嵌套 PDT 的缓存可能会过期。当这种情况发生时,Looker 会为较低级别的 PDT 触发一个新的、重复的构建请求,而初始作业仍在数据仓库中处理,从而导致冲突。

为解决或防止此错误,请遵循以下最佳实践:

  • 增加缓存保留期限: 将 PDT 的缓存保留期限(max_cache_agepersist_for)设置为至少是完成所有嵌套 PDT 的完整构建所需最大时间的两到三倍。
  • 增加数据组刷新间隔: 为深度嵌套的 PDT 构建留出足够的时间,从而降低构建过程重叠的风险。

提高光动力疗法性能

当你创建持久化派生表(PDT)性能可能是一个问题。特别是当表非常大时,查询表的速度可能会很慢,就像数据库中任何大表都会出现这种情况一样。

您可以通过过滤数据或通过控制 PDT 中数据的排序和索引方式来提高性能。

添加过滤条件以限制数据集

对于特别大的数据集,行数过多会减慢对持久派生表 (PDT) 的查询速度。如果您通常只查询最近的数据,请考虑在 PDT 的 WHERE 子句中添加一个过滤器,将表的数据限制为 90 天或更短。这样,每次重建表时,只会向表中添加相关数据,从而大大加快查询速度。然后,您可以创建一个单独的、更大的 PDT 用于历史分析,以便既可以快速查询最近的数据,也可以查询旧数据。

使用 indexessortkeysdistribution

创建大型持久派生表 (PDT) 时,对表进行索引(对于 MySQL 或 Postgres 等方言)或添加排序键和分布(对于 Redshift)有助于提高性能。

通常最好在 ID 或日期字段上添加 indexes 参数。

对于 Redshift,通常最好在 ID 或日期字段上添加 sortkeys 参数,并在用于连接的字段上添加 distribution 参数。

以下设置控制持久派生表 (PDT) 中的数据如何排序和建立索引。这些设置是可选的,但强烈建议您进行设置:

  • 对于 Redshift 和 Aster,使用 distribution 参数指定列名,该列的值用于将数据分散到集群中。当两个表通过 distribution 参数中指定的列连接时,数据库可以在同一节点上找到连接数据,从而最大限度地减少节点间的 I/O。
  • 对于 Redshift,将 distribution_style 参数设置为 all,以指示数据库在每个节点上保留数据的完整副本。当连接相对较小的表时,通常使用这种方法来最大限度地减少节点间的 I/O。将此值设置为 even,以指示数据库在不使用分布列的情况下将数据均匀地分布在集群中。只有在未指定 distribution 时才能指定此值。
  • 对于 Redshift,请使用 sortkeys 参数。这些值用于指定 PDT 的哪些列用于对磁盘上的数据进行排序,以便更轻松地进行搜索。在 Redshift 上,您可以使用 sortkeysindexes,但不能同时使用这两者。
  • 在大多数数据库中,请使用 indexes 参数。这些值用于指定 PDT 的哪些列编入索引。(在 Redshift 上,索引用于生成交错排序键。)