在 Looker 中,派生表是一种查询,其结果的使用方式就像是数据库中的实际表一样。
例如,您可能有一个名为 orders
的数据库表,其中包含许多列。您想要计算一些客户级汇总指标,例如每个客户下达的订单数量或每个客户下达的第一个订单的时间。使用原生派生表或基于 SQL 的派生表,您可以创建一个名为 customer_order_summary
且包含这些指标的新数据库表。
然后,您可以像使用数据库中的任何其他表一样使用 customer_order_summary
派生表。
如需了解派生表的常见用例,请参阅 Looker 实战宝典:在 Looker 中充分利用派生表。
原生派生表和基于 SQL 的派生表
如需在 Looker 项目中创建派生表,请在 view 参数下使用 derived_table
参数。在 derived_table
参数内,您可以通过以下两种方式之一定义派生表的查询:
- 对于原生派生表,您可以使用基于 LookML 的查询定义派生表。
- 对于基于 SQL 的派生表,您可以通过 SQL 查询来定义派生表。
例如,以下视图文件展示了如何使用 LookML 根据 customer_order_summary
派生表创建视图。两个版本的 LookML 说明了如何使用 LookML 或 SQL 创建等效的派生表来定义派生表的查询:
- 原生派生表在
explore_source
参数中使用 LookML 定义查询。在此示例中,查询基于现有的orders
视图,该视图是在一个单独的文件中定义的(此示例中未显示)。原生派生表中的explore_source
查询引入了orders
视图文件中的customer_id
、first_order
和total_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 ;; } }
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 ;; } }
这两个版本都基于 orders
表创建一个名为 customer_order_summary
的视图,其中包含 customer_id
、first_order,
和 total_amount
列。
除了 derived_table
参数及其子参数之外,此 customer_order_summary
视图的运作方式与任何其他视图文件一样。无论您使用 LookML 还是 SQL 定义派生表的查询,都可以根据派生表的列创建 LookML 测量和维度。
定义派生表后,您可以像使用数据库中的任何其他表一样使用它。
原生派生表
原生派生表基于您使用 LookML 术语定义的查询。如需创建原生派生表,您可以在视图参数的 derived_table
参数内使用 explore_source
参数。您可以通过引用模型中的 LookML 维度或测量来创建原生派生表的列。请参阅上一个示例中的原生派生表视图文件。
与基于 SQL 的派生表相比,在对数据进行建模时,原生派生表更易于阅读和理解。
如需详细了解如何创建原生派生表,请参阅创建原生派生表文档页面。
基于 SQL 的派生表
如需创建基于 SQL 的派生表,您需要使用 SQL 术语定义查询,并使用 SQL 查询在表中创建列。您不能在基于 SQL 的派生表中引用 LookML 维度和测量值。请参阅上例中的基于 SQL 的派生表视图文件。
最常见的是,您可以使用视图参数的 derived_table
参数中的 sql
参数来定义 SQL 查询。
在 Looker 中创建基于 SQL 的查询时,一个实用的快捷方式是使用 SQL Runner 创建 SQL 查询并将其转换为派生表定义。
某些极端情况将不允许使用 sql
参数。在这种情况下,Looker 支持使用以下参数为永久派生表 (PDT) 定义 SQL 查询:
create_process
:当您对 PDT 使用sql
参数时,Looker 会在后台将方言的CREATE TABLE
数据定义语言 (DDL) 语句封装在您的查询中,以便通过 SQL 查询创建 PDT。某些方言不支持单步使用 SQLCREATE TABLE
语句。对于这些方言,您无法使用sql
参数创建 PDT。您可以改为使用create_process
参数分多个步骤创建 PDT。如需了解相关信息和示例,请参阅create_process
参数文档页面。sql_create
:如果您的用例需要自定义 DDL 命令,并且您的方言支持 DDL(例如 Google 预测性 BigQuery ML),您可以使用sql_create
参数创建 PDT,而不是使用sql
参数。如需了解相关信息和示例,请参阅sql_create
文档页面。
无论您使用的是 sql
、create_process
还是 sql_create
参数,在所有这些情况下,您都是使用 SQL 查询定义派生表,因此这些派生表都属于基于 SQL 的派生表。
定义基于 SQL 的派生表时,请务必使用 AS
为每个列指定一个干净的别名。这是因为您需要在维度中引用结果集的列名称,例如 ${TABLE}.first_order
。因此,上一个示例使用的是 MIN(DATE(time)) AS first_order
,而不是直接使用 MIN(DATE(time))
。
临时和永久性派生表
除了原生派生表和基于 SQL 的派生表之间的区别之外,临时派生表(不会写入数据库)和永久性派生表 (PDT) 之间也有区别,后者会写入数据库中的架构。
原生派生表和基于 SQL 的派生表可以是临时表,也可以是永久性表。
临时派生表
之前显示的派生表是临时派生表的示例。它们是临时的,因为 derived_table
参数中未定义任何持久化策略。
临时派生表不会写入数据库。当用户运行涉及一个或多个派生表的探索查询时,Looker 会使用派生表的 SQL 以及请求的字段、联接和过滤值的方言专用组合来构建 SQL 查询。如果之前运行过该组合,并且结果在缓存中仍然有效,Looker 将使用缓存的结果。如需详细了解 Looker 中的查询缓存,请参阅缓存查询文档页面。
否则,如果 Looker 无法使用缓存结果,则每当用户从临时派生表中请求数据时,Looker 都必须对您的数据库运行新查询。因此,您应确保临时派生表的性能良好,并且不会给数据库带来过多压力。如果查询需要一些时间才能运行,PDT 通常是更好的选择。
临时派生表支持的数据库方言
为了让 Looker 支持 Looker 项目中的派生表,您的数据库方言也必须支持派生表。下表显示了最新版 Looker 中支持派生表的方言:
方言 | 是否支持? |
---|---|
阿克蒂安雪崩 | 是 |
Amazon Athena | 是 |
Amazon Aurora MySQL | 是 |
Amazon Redshift | 是 |
Apache Druid | 是 |
Apache Druid 0.13+ | 是 |
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 及更高版本 | 是 |
带有原生驱动程序的 Cloudera Impala | 是 |
DataVirtuality | 是 |
Databricks | 是 |
Denodo 7 购物中心 | 是 |
迪诺多 8 号星 | 是 |
Dremio | 是 |
Dremio 11+ | 是 |
Exasol | 是 |
Firebolt | 是 |
Google BigQuery 旧版 SQL | 是 |
Google BigQuery 标准 SQL | 是 |
Google Cloud PostgreSQL | 是 |
Google Cloud SQL | 是 |
Google Spanner | 是 |
Greenplum | 是 |
HyperSQL | 是 |
IBM Netezza | 是 |
MariaDB | 是 |
Microsoft Azure PostgreSQL | 是 |
Microsoft Azure SQL 数据库 | 是 |
Microsoft Azure Synapse 分析 | 是 |
Microsoft SQL Server 2008 及更高版本 | 是 |
Microsoft SQL Server 2012 及更高版本 | 是 |
Microsoft SQL Server 2016 | 是 |
Microsoft SQL Server 2017 及更高版本 | 是 |
MongoBI | 是 |
MySQL | 是 |
MySQL 8.0.12 及更高版本 | 是 |
Oracle | 是 |
Oracle ADWC | 是 |
PostgreSQL 9.5 及更高版本 | 是 |
PostgreSQL 9.5 之前的版本 | 是 |
PrestoDB | 是 |
PrestoSQL | 是 |
SAP HANA 2 及更高版本 | 是 |
SingleStore | 是 |
单一商店 7+ | 是 |
Snowflake | 是 |
TeraData | 是 |
Trino | 是 |
矢量 | 是 |
Vertica | 是 |
永久性派生表
永久性派生表 (PDT) 是一种会写入数据库中的临时架构,并根据您使用持久性策略指定的时间表进行重新生成的派生表。
PDT 可以是原生派生表或基于 SQL 的派生表。
PDT 的要求
如需在 Looker 项目中使用永久性派生表 (PDT),您需要满足以下条件:
- 支持 PDT 的数据库方言。请参阅本页面后面的 PDT 支持的数据库方言部分,查看支持基于 SQL 的永久性派生表和永久性原生派生表的方言列表。
- 数据库中的测试架构。这可以是数据库中的任何架构,但我们建议您创建一个仅用于此目的的新架构。您的数据库管理员必须为 Looker 数据库用户配置具有写入权限的架构。
- Looker 连接,其启用 PDT 切换开关处于开启状态。这通常是在您初始配置 Looker 连接时设置的(如需了解数据库方言的说明,请参阅 Looker 方言文档页面),但您也可以在初始设置后为连接启用 PDT。
PDT 支持的数据库方言
为了让 Looker 支持 Looker 项目中的永久性派生表 (PDT),您的数据库方言也必须支持它们。
如需支持任何类型的 PDT(基于 LookML 或基于 SQL),方言必须支持写入数据库,以及满足其他要求。有一些只读数据库配置不允许持久化正常工作(最常见的是 Postgres 热交换副本数据库)。在这些情况下,您可以改用临时派生表。
下表显示了最新版 Looker 中支持基于 SQL 的永久性派生表的方言:
方言 | 是否支持? |
---|---|
阿克蒂安雪崩 | 是 |
Amazon Athena | 是 |
Amazon Aurora MySQL | 是 |
Amazon Redshift | 是 |
Apache Druid | 否 |
Apache Druid 0.13 及更高版本 | 否 |
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 及更高版本 | 是 |
带有原生驱动程序的 Cloudera Impala | 是 |
DataVirtuality | 否 |
Databricks | 是 |
Denodo 7 购物中心 | 否 |
迪诺多 8 号星 | 否 |
Dremio | 否 |
Dremio 11+ | 否 |
Exasol | 是 |
Firebolt | 否 |
Google BigQuery 旧版 SQL | 是 |
Google BigQuery 标准 SQL | 是 |
Google Cloud PostgreSQL | 是 |
Google Cloud SQL | 是 |
Google Spanner | 否 |
Greenplum | 是 |
HyperSQL | 否 |
IBM Netezza | 是 |
MariaDB | 是 |
Microsoft Azure PostgreSQL | 是 |
Microsoft Azure SQL 数据库 | 是 |
Microsoft Azure Synapse 分析 | 是 |
Microsoft SQL Server 2008 及更高版本 | 是 |
Microsoft SQL Server 2012 及更高版本 | 是 |
Microsoft SQL Server 2016 | 是 |
Microsoft SQL Server 2017 及更高版本 | 是 |
MongoBI | 否 |
MySQL | 是 |
MySQL 8.0.12 及更高版本 | 是 |
Oracle | 是 |
Oracle ADWC | 是 |
PostgreSQL 9.5 及更高版本 | 是 |
PostgreSQL 9.5 之前的版本 | 是 |
PrestoDB | 是 |
PrestoSQL | 是 |
SAP HANA 2 及更高版本 | 是 |
SingleStore | 是 |
单一商店 7+ | 是 |
Snowflake | 是 |
TeraData | 是 |
Trino | 是 |
矢量 | 是 |
Vertica | 是 |
为了支持永久性原生派生表(具有基于 LookML 的查询),该方言还必须支持 CREATE TABLE
DDL 函数。以下是最新版 Looker 中支持永久性原生(基于 LookML)派生表的方言列表:
方言 | 是否支持? |
---|---|
阿克蒂安雪崩 | 是 |
Amazon Athena | 是 |
Amazon Aurora MySQL | 是 |
Amazon Redshift | 是 |
Apache Druid | 否 |
Apache Druid 0.13 及更高版本 | 否 |
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 及更高版本 | 是 |
带有原生驱动程序的 Cloudera Impala | 是 |
DataVirtuality | 否 |
Databricks | 是 |
Denodo 7 购物中心 | 否 |
迪诺多 8 号星 | 否 |
Dremio | 否 |
Dremio 11+ | 否 |
Exasol | 是 |
Firebolt | 否 |
Google BigQuery 旧版 SQL | 是 |
Google BigQuery 标准 SQL | 是 |
Google Cloud PostgreSQL | 是 |
Google Cloud SQL | 否 |
Google Spanner | 否 |
Greenplum | 是 |
HyperSQL | 否 |
IBM Netezza | 是 |
MariaDB | 是 |
Microsoft Azure PostgreSQL | 是 |
Microsoft Azure SQL 数据库 | 是 |
Microsoft Azure Synapse 分析 | 是 |
Microsoft SQL Server 2008 及更高版本 | 是 |
Microsoft SQL Server 2012 及更高版本 | 是 |
Microsoft SQL Server 2016 | 是 |
Microsoft SQL Server 2017 及更高版本 | 是 |
MongoBI | 否 |
MySQL | 是 |
MySQL 8.0.12 及更高版本 | 是 |
Oracle | 是 |
Oracle ADWC | 是 |
PostgreSQL 9.5 及更高版本 | 是 |
PostgreSQL 9.5 之前的版本 | 是 |
PrestoDB | 是 |
PrestoSQL | 是 |
SAP HANA 2 及更高版本 | 是 |
SingleStore | 是 |
单一商店 7+ | 是 |
Snowflake | 是 |
TeraData | 是 |
Trino | 是 |
矢量 | 是 |
Vertica | 是 |
逐步构建 PDT
增量 PDT 是指 Looker 通过将新数据附加到表中(而不是重新构建整个表)构建的永久性派生表 (PDT)。
如果您的方言支持增量 PDT,而 PDT 使用基于触发器的持久性策略(datagroup_trigger
、sql_trigger_value
或 interval_trigger
),则可以将 PDT 定义为增量 PDT。
如需了解详情,请参阅增量 PDT 文档页面。
增量 PDT 支持的数据库方言
为了让 Looker 在 Looker 项目中支持增量 PDT,您的数据库方言也必须支持增量 PDT。下表显示了最新版 Looker 中哪些方言支持增量 PDT:
方言 | 是否支持? |
---|---|
阿克蒂安雪崩 | 否 |
Amazon Athena | 否 |
Amazon Aurora MySQL | 否 |
Amazon Redshift | 是 |
Apache Druid | 否 |
Apache Druid 0.13 及更高版本 | 否 |
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+ | 否 |
带有原生驱动程序的 Cloudera Impala | 否 |
DataVirtuality | 否 |
Databricks | 是 |
Denodo 7 购物中心 | 否 |
迪诺多 8 号星 | 否 |
Dremio | 否 |
Dremio 11+ | 否 |
Exasol | 否 |
Firebolt | 否 |
Google BigQuery 旧版 SQL | 否 |
Google BigQuery 标准 SQL | 是 |
Google Cloud PostgreSQL | 是 |
Google Cloud SQL | 否 |
Google Spanner | 否 |
Greenplum | 是 |
HyperSQL | 否 |
IBM Netezza | 否 |
MariaDB | 否 |
Microsoft Azure PostgreSQL | 是 |
Microsoft Azure SQL 数据库 | 否 |
Microsoft Azure Synapse 分析 | 是 |
Microsoft SQL Server 2008 及更高版本 | 否 |
Microsoft SQL Server 2012 及更高版本 | 否 |
Microsoft SQL Server 2016 | 否 |
Microsoft SQL Server 2017 及更高版本 | 否 |
MongoBI | 否 |
MySQL | 是 |
MySQL 8.0.12 及更高版本 | 是 |
Oracle | 否 |
Oracle ADWC | 否 |
PostgreSQL 9.5 及更高版本 | 是 |
PostgreSQL 9.5 之前的版本 | 是 |
PrestoDB | 否 |
PrestoSQL | 否 |
SAP HANA 2 及更高版本 | 否 |
SingleStore | 否 |
SingleStore 7+ | 否 |
Snowflake | 是 |
TeraData | 否 |
Trino | 否 |
矢量 | 否 |
Vertica | 是 |
创建 PDT
如需将派生表转换为永久性派生表 (PDT),请为表定义保留策略。为了优化效果,您还应该添加优化策略。
持久化策略
派生表的持久性可由 Looker 管理,对于支持具体化视图的方言,则由数据库使用具体化视图管理。
如需使派生表持久化,请将以下参数之一添加到 derived_table
定义中:
- Looker 管理的持久性参数:
- 由数据库管理的持久性参数:
使用基于触发器的持久化策略(datagroup_trigger
、sql_trigger_value
和 interval_trigger
)时,Looker 会在数据库中维护 PDT,直到系统触发用于重建的 PDT。触发 PDT 后,Looker 会重新构建 PDT 以替换之前的版本。这意味着,使用基于触发器的 PDT,您的用户无需等待构建 PDT,即可从 PDT 获得与“探索”类查询相关的答案。
datagroup_trigger
数据组是创建持久性的最灵活方法。如果您使用 sql_trigger
或 interval_trigger
定义了 datagroup,则可以使用 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 的 persist_for
参数中指定的时间段内在数据库中维护 PDT。如果用户在 persist_for
时间内查询 PDT,Looker 会尽可能使用缓存的结果,否则会针对该 PDT 运行查询。
persist_for
时间过后,Looker 会从数据库中清除 PDT,并在用户下次查询 PDT 时重新构建 PDT,这意味着该查询需要等待重新构建。
Looker 的重新生成器不会自动重新构建使用 persist_for
的 PDT,只有 PDT 的依赖项级联的情况除外。当 persist_for
表属于与基于触发器的 PDT(使用 datagroup_trigger
、interval_trigger
或 sql_trigger_value
持久性策略的 PDT)的依赖项级联的一部分时,重新生成器将监控并重建 persist_for
表,以便在级联中重建其他表。请参阅本页中的Looker 如何构建级联派生表部分。
materialized_view: yes
借助具体化视图,您可以利用数据库的功能在 Looker 项目中保留派生表。如果您的数据库方言支持具体化视图,并且您的 Looker 连接配置为启用 Enable PDTs 切换开关,则您可以通过为派生表指定 materialized_view: yes
来创建具体化视图。原生派生表和基于 SQL 的派生表均支持具体化视图。
与永久性派生表 (PDT) 类似,具体化视图是一种查询结果,会以表的形式存储在数据库的临时架构中。PDT 与具体化视图之间的主要区别在于表的刷新方式:
- 对于 PDT,持久性策略在 Looker 中定义,而持久性由 Looker 管理。
- 对于具体化视图,数据库负责维护和刷新表中的数据。
因此,若要使用具体化视图功能,您需要对方言及其特性有深入的了解。在大多数情况下,只要数据库在具体化视图所查询的表中检测到新数据,数据库就会刷新具体化视图。具体化视图最适合需要实时数据的场景。
如需了解方言支持、要求和重要注意事项,请参阅 materialized_view
参数文档页面。
优化策略
由于永久派生表 (PDT) 存储在数据库中,因此您应根据方言的支持情况,使用以下策略优化 PDT:
例如,如需向派生表示例添加持久性,您可以将其设置为在数据集群 orders_datagroup
触发时重新构建,并在 customer_id
和 first_order
上添加索引,如下所示:
view: customer_order_summary {
derived_table: {
explore_source: orders {
...
}
datagroup_trigger: orders_datagroup
indexes: ["customer_id", "first_order"]
}
}
如果您未添加索引(或相应方言的等效项),Looker 会警告您应添加索引以提高查询性能。
PDT 使用场景
永久性派生表 (PDT) 非常有用,因为它们可以通过将查询结果保存在表中来提高查询性能。
一般来说,在绝对必要之前,开发者应尝试在不使用 PDT 的情况下对数据进行建模。
在某些情况下,数据可以通过其他方式进行优化。例如,添加索引或更改列的数据类型或许可以解决问题,而无需创建 PDT。请务必使用 Explain from SQL Runner 工具来分析慢查询的执行计划。
除了缩短经常运行的查询的查询时间和数据库负载之外,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_B
,TABLE_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
是字面量字符串。
在下一个示例中,clean_events
PDT 是根据数据库中的 events
表创建的。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_B
,以此类推,直到 TABLE_C
完成生成,Looker 才能提供查询结果。(由于无需 TABLE_D
即可回答此查询,因此 Looker 目前不会重新构建 TABLE_D
。)
如需查看使用相同数据群组的级联 PDT 的示例场景,请参阅 datagroup
参数文档页面。
同样的基本逻辑也适用于 PDT:Looker 会构建回答查询所需的所有表,一直到依赖项链的顶部。但对于 PDT,表通常已存在,无需重新构建。通过对级联 PDT 进行标准用户查询,仅当数据库中没有有效 PDT 版本时,Looker 才会在级联中重新构建 PDT。如果您要在级联中强制重新构建所有 PDT,可以通过探索手动为查询重新构建表。
请务必了解一个重要的逻辑要点:在 PDT 级联的情况下,依赖的 PDT 本质上是在查询其依赖的 PDT。这一点对于使用 persist_for
策略的 PDT 尤为重要。通常,persist_for
PDT 会在用户查询它们时构建,并保留在数据库中直到其 persist_for
间隔时间结束,然后在用户下次查询它们时才会重新构建。不过,如果 persist_for
PDT 是基于触发器的 PDT(使用 datagroup_trigger
、interval_trigger
或 sql_trigger_value
持久化策略的 PDT)的级联的一部分,那么每当其依赖的 PDT 被重新构建时,系统都会查询 persist_for
PDT。因此,在这种情况下,persist_for
PDT 将根据其依赖 PDT 的时间表重新构建。这意味着,persist_for
PDT 可能会受到其依赖项的持久化策略的影响。
手动为查询重新构建持久表
用户可以在“探索”的菜单中选择重新构建派生表并运行选项,以替换持久性设置,并重新构建“探索”中当前查询所需的所有永久性派生表 (PDT) 和汇总表:
此选项仅对拥有 develop
权限的用户显示,且只有在“探索”查询加载完成后。
重新构建派生表并运行选项会重新构建回答查询所需的所有永久表(所有 PDT 和汇总表),无论其持久性策略如何。这包括当前查询中的所有汇总表和 PDT,以及当前查询中的汇总表和 PDT 引用的所有汇总表和 PDT。
对于增量 PDT,请参阅重新构建派生表和Run 选项触发新增量的构建。使用增量 PDT 时,增量包括 increment_key
参数中指定的时间段,以及 increment_offset
参数中指定的先前时间段的数量(如果有)。请参阅增量 PDT 文档页面,查看一些示例场景,了解增量 PDT 是如何根据其配置进行构建的。
对于级联 PDT,这意味着从顶部开始重新构建级联中的所有派生表。这与在临时派生表级联中查询表时的行为相同:
请注意有关手动重新构建派生表的以下事项:
- 对于发起重新构建派生表并运行操作的用户,查询将等待表重新构建完毕,然后再加载结果。其他用户的查询仍会使用现有表。重新构建永久表后,所有用户都将使用重新构建的表。尽管这一流程旨在避免干扰其他用户的查询,那么这些用户仍可能会受到数据库额外负载的影响。如果您遇到以下情况,即在工作时间触发重新构建可能会给数据库带来不可接受的压力,则可能需要告知用户,他们绝不应在这些时间重新构建特定的 PDT 或汇总表。
如果用户处于开发模式,并且探索基于开发表,则重新构建派生表并运行操作将为探索重新构建开发表,而不是生产表。但是,如果“开发模式下的探索”使用的是派生表的生产版本,则将重新构建生产表。如需了解开发表和生产表,请参阅开发模式下的持久化表。
对于由 Looker 托管的实例,如果派生表的重建时间超过一小时,则表将无法成功重建,并且浏览器会话将超时。如需详细了解可能会影响 Looker 进程的超时问题,请参阅管理设置 - 查询文档页面中的查询超时和队列部分。
开发模式下的永久表
Looker 在开发模式下管理持久表时会有一些特殊行为。
如果您在开发模式下查询某个持久表,而未对其定义进行任何更改,Looker 将查询该表的正式版。如果您确实更改了表定义,而更改会影响表中的数据或表的查询方式,则系统会在您下次在开发模式下查询表时创建表的新开发版本。有了这样的开发表格,您就可以在不干扰最终用户的情况下测试更改。
促使 Looker 创建开发表的原因
无论您是否处于开发模式,Looker 都会尽可能使用现有的生产表来回答查询。但在某些情况下,Looker 无法在开发模式下使用生产表进行查询:
- 如果您的永久表具有用于缩小其数据集的参数,以便在开发模式下更快地运行
- 您对持久性表的定义进行了更改,而这些更改会影响表中的数据
如果您处于开发模式,并且要查询基于 SQL 的派生表,该表使用包含 if prod
和 if dev
语句的条件 WHERE
子句定义,Looker 将会构建一个开发表。
对于在开发模式下没有用于缩小数据集范围的参数的永久表,Looker 会使用表的生产版本来回答开发模式下的查询,除非您更改表的定义,然后在开发模式下查询表。这适用于对表进行的任何更改,只要这些更改会影响表中的数据或表的查询方式。
以下是一些会促使 Looker 创建永久表的开发版本的更改类型示例(只有在您在进行这些更改后随后查询该表时,Looker 才会创建该表):
- 更改永久表所基于的查询,例如修改永久表本身或任何所需表(如果级联派生表)中的
explore_source
、sql
、query
、sql_create
或create_process
参数 - 更改表的保留策略,例如修改表的
datagroup_trigger
、sql_trigger_value
、interval_trigger
或persist_for
参数 - 更改派生表的
view
的名称 - 更改增量 PDT 的
increment_key
或increment_offset
- 更改关联模型使用的
connection
如果更改不修改表的数据或影响 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 小时,则该表的开发版本会被标记为已过期,并且不会用于查询。您可以使用 Looker IDE 或永久派生表页面的开发标签页检查未构建的 PDT。如果您有未构建的 PDT,可以在进行更改之前直接在开发模式下对其进行查询,以便开发表可在生产环境中使用。
- 如果持久化表包含
dev_filters
参数(对于原生派生表)或使用if prod
和if dev
语句的条件WHERE
子句(对于基于 SQL 的派生表),则开发表无法用作生产版本,因为开发版本的数据集较短。如果是这种情况,在开发完表之后部署更改之前,您可以注释掉dev_filters
参数或条件WHERE
子句,然后在开发模式下查询该表。然后,Looker 会构建一个完整版表,供您在部署更改时用于生产环境。
否则,如果您在没有可用作生产表的有效开发表时部署更改,Looker 将在下次以生产模式查询表时(对于使用 persist_for
策略的持久表)或下次运行再生器时(对于使用 datagroup_trigger
、interval_trigger
或 sql_trigger_value
的持久表)重新构建表。
在开发模式下检查未构建的 PDT
如果您在将更改部署到永久派生表 (PDT) 或汇总表时,开发表会保留在数据库中,Looker 通常会将开发表用作生产表,这样用户在查询表时就不必等待表构建。如需了解详情,请参阅本页中的Looker 会将开发表保留多长时间和是什么原因促使 Looker 创建开发表部分。
因此,最好在部署到生产环境时构建所有 PDT,以便可以立即将表用作生产环境版本。
您可以在 Project Health 面板中检查项目是否存在未构建的 PDT。点击 Looker IDE 中的 Project Health 图标,打开 Project Health 面板。然后点击 Validate PDT Status(验证 PDT 状态)按钮。
如果有未构建的 PDT,Project Health 面板会列出它们:
如果您拥有 see_pdts
权限,则可以点击转到 PDT 管理按钮。Looker 将打开 Persistent Derived Tables 页面的开发标签页,并对结果进行过滤,以显示您的特定 LookML 项目。在该页面中,您可以查看哪些开发 PDT 已构建和未构建,以及访问其他问题排查信息。如需了解详情,请参阅管理设置 - 永久性派生表文档页面。
在项目中找到未构建的 PDT 后,您可以打开用于查询表的“探索”,然后使用“探索”菜单中的重新构建派生表并运行选项来构建开发版本。请参阅本页面中的为查询手动重建永久表部分。
表共享和清理
在任何给定的 Looker 实例中,如果表具有相同的定义和相同的持久化方法设置,Looker 会在用户之间共享这些持久化表。此外,如果表的定义不复存在,Looker 会将该表标记为已过期。
这样做有几个好处:
- 如果您在开发模式下未对表进行任何更改,则您的查询将使用现有的生产表。除非您的表是基于 SQL 的派生表,并且该表使用包含
if prod
和if dev
语句的条件WHERE
子句定义,否则就会出现这种情况。如果表是使用条件WHERE
子句定义的,那么当您在开发模式下查询该表时,Looker 会构建一个开发表。(对于包含dev_filters
参数的原生派生表,Looker 具有使用生产表在开发模式下回答查询的逻辑,除非您更改表的定义,然后在开发模式下查询表。) - 如果两位开发者碰巧在开发模式下对表进行了相同的更改,则他们将共享同一个开发表。
- 一旦将更改从开发模式推送到生产模式,旧的生产定义就不再存在,因此旧的生产表会被标记为已过期,将被丢弃。
- 如果您决定舍弃您的开发模式更改,则该表定义不再存在,因此不需要的开发表将被标记为已过期,将被丢弃。
在开发模式下更快地工作
在某些情况下,您创建的永久派生表 (PDT) 需要很长时间才能生成,如果您在开发模式下测试大量更改,这可能会很耗时。对于此类情况,您可以提示 Looker 在开发模式下创建派生表的较小版本。
对于原生派生表,您可以使用 explore_source
的 dev_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_filters
和 filters
都为同一列指定了过滤条件,则对于表的开发版本,dev_filters
优先于 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) 被定义并首次运行或由再生器触发以根据其持久性策略进行重新构建后,Looker 将执行以下步骤:
- 使用派生表 SQL 构建 CREATE TABLE AS SELECT(或 CTAS)语句并执行它。例如,如需重新构建名为
customer_orders_facts
的 PDT,请执行以下命令:CREATE TABLE tmp.customer_orders_facts AS SELECT ... FROM ... WHERE ...
- 构建表时发出语句以创建索引
- 将表从 LC$..(“Looker Create”)重命名为 LR$..(“Looker Read”),以表明该表可供使用
- 删除不再使用的任何旧版表
这有几个重要的影响:
- 用于构成派生表的 SQL 语句必须在 CTAS 语句中有效。
- SELECT 语句的结果集中的列别名必须是有效的列名称。
- 指定分布、排序键和索引时使用的名称必须是派生表的 SQL 定义中列出的列名称,而不是在 LookML 中定义的字段名称。
Looker 再生成器
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
表是触发器保留表的依赖项级联时。在这种情况下,Looker 重新生成器将启动 persist_for
表的重新构建,因为需要该表来重建级联中的其他表。否则,重新生成器不会监控使用 persist_for
策略的持久化表。
Looker 重新生成器周期的开始周期是由您的 Looker 管理员在数据库连接的数据组和 PDT 维护时间表设置中配置的(默认为五分钟间隔)。不过,在完成上一个周期的所有检查和 PDT 重建之前,Looker 重新生成器不会启动新的周期。这意味着,如果您有长时间运行的 PDT build,Looker 再生器周期的运行频率可能不如数据组和 PDT 维护时间表设置中所定义的频率。其他因素可能会影响重新构建表所需的时间,如本页的实现持久表的重要注意事项部分所述。
如果 PDT 构建失败,重新生成器可能会尝试在下一个重新生成器周期中重新构建表:
- 如果数据库连接上启用了重试失败的 PDT 构建设置,Looker 重新生成器将尝试在下一个重新生成器周期内重新构建表,即使表未满足触发条件也是如此。
- 如果停用了重试失败的 PDT 构建设置,则在满足 PDT 的触发条件之前,Looker 重建程序不会尝试重新构建表。
如果用户在构建过程中从保留表请求数据,但查询结果不在缓存中,Looker 会检查现有表是否仍然有效。(如果旧表与新版表不兼容,则可能无效。如果新表的定义不同、使用不同的数据库连接或使用其他版本的 Looker 创建,就可能会出现这种情况。)如果现有表仍然有效,Looker 将返回现有表中的数据,直到新表构建完毕。否则,如果现有表无效,Looker 会在重新构建新表后提供查询结果。
实现持久化表的重要注意事项
考虑到永久性表(PDT 和汇总表)的实用性,您可以很容易地在 Looker 实例上累积许多此类表。可能会造成这样一种场景:Looker 再生成器需要同时构建多个表。尤其是对于级联表或长时间运行的表,您可以创建表在重建之前需要等待很长时间的场景,或者在数据库努力生成表时,用户在从表中获取查询结果时会遇到延迟的情况。
Looker 的重新生成器会检查 PDT 触发器,以确定是否应重新构建触发器保留的表。重新生成器周期的设置间隔由 Looker 管理员在数据库连接的数据组和 PDT 维护时间表设置中配置(默认间隔为 5 分钟)。
以下几个因素可能会影响重建表所需的时间:
- Looker 管理员可能会通过数据库连接的 Datagroup and PDT Maintenance Schedule 设置更改了 regenerator 触发器检查的间隔时间。
- Looker 再生器会等到完成上一个周期的所有检查和 PDT 重新构建后,才会开始新的周期。因此,如果您有长时间运行的 PDT build,Looker 重新生成器周期可能没有 Datagroup 和 PDT 维护时间表设置的频率。
- 默认情况下,重新生成器可以通过连接一次发起一个 PDT 或汇总表的重建。Looker 管理员可以使用连接设置中的 PDT 构建器连接数上限字段调整重新生成器允许的并发重建数量。
- 由同一
datagroup
触发的所有 PDT 和汇总表都将在同一重新生成过程中重新构建。如果有许多表直接或因级联依赖项而使用数据集,这可能会造成较大的负载。
除了前面的注意事项之外,还有一些情况应避免向派生表添加持久化:
- 派生表何时进行扩展 - PDT 的每次扩展都会在您的数据库中创建一个表的新副本。
- 当派生表使用模板化过滤器或 Liquid 参数时 - 使用模板化过滤器或 Liquid 参数的派生表不支持持久性。
- 如果原生派生表是通过搭配使用用户属性和
access_filters
或sql_always_where
的探索构建的,系统会在您的数据库中为指定的每个可能的用户属性值构建表的副本。 - 当基础数据频繁更改且您的数据库方言不支持增量 PDT 时。
- 创建 PDT 所需的费用和时间过高。
队列中可能包含许多需要在每个周期检查和重新构建的持久表,具体取决于 Looker 连接中持久表的数量和复杂性,因此在 Looker 实例上实现派生表时,请务必注意这些因素。
通过 API 批量管理 PDT
随着您在实例中创建的永久性派生表 (PDT) 越来越多,监控和管理按不同时间表刷新的 PDT 会变得越来越复杂。请考虑使用 Looker 的 Apache Airflow 集成来管理 PDT 时间表以及其他 ETL 和 ELT 流程。
监控和问题排查 PDT
如果您使用永久性派生表 (PDT),尤其是级联 PDT,查看 PDT 的状态会很有帮助。您可以使用 Looker 的永久性派生表管理页面查看 PDT 的状态。如需了解详情,请参阅管理设置 - 永久派生表文档页面。
尝试排查 PDT 问题时,请注意以下事项:
- 在调查 PDT 事件日志时,请特别注意开发表和生产表之间的区别。
- 验证未对 Looker 存储永久性派生表的暂存架构进行任何更改。如果进行了更改,您可能需要更新 Looker 管理部分中的连接设置,然后可能需要重启 Looker 以恢复正常的 PDT 功能。
- 确定是所有 PDT 都存在问题,还是只有一个 PDT 存在问题。如果其中一个出现问题,则问题可能由 LookML 或 SQL 错误引起。
- 确定 PDT 的问题是否与安排重新构建的时间相对应。
- 请确保所有
sql_trigger_value
查询都能成功评估,并且仅返回一行和一列。对于基于 SQL 的 PDT,您可以通过在 SQL Runner 中运行它们来实现此目的。(应用LIMIT
可防止失控查询。)如需详细了解如何使用 SQL Runner 调试派生表,请参阅使用 SQL 运行程序测试派生表 社区帖子。 - 对于基于 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 中的 Show Processes 按钮。如果有大量进程处于活跃状态,则可能会降低查询速度。
- 监控查询中的注释。请参阅本页面中的查询 PDT 的备注部分。
查询 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 必须为探索的查询生成 PDT,则 PDT 生成备注将显示在探索的 SQL 标签页中。该注释将显示在 SQL 语句的顶部。
最后,在查询管理页面上,对于每个查询,查询详情弹出式窗口的信息标签页中的消息字段中都会显示 PDT 生成注释。
在失败后重新构建 PDT
当永久性派生表 (PDT) 发生失败时,查询该 PDT 时会发生以下情况:
- 如果之前运行过相同的查询,Looker 将使用缓存中的结果。(有关工作原理的说明,请参阅缓存查询文档页面。)
- 如果结果不在缓存中,Looker 会从数据库中的 PDT(如果存在有效版本的 PDT)中提取结果。
- 如果数据库中没有有效的 PDT,Looker 将尝试重新构建该 PDT。
- 如果无法重新构建 PDT,Looker 会针对查询返回错误。下次查询 PDT 或 PDT 的持久化策略触发重建时,Looker 再生器会尝试重新构建 PDT。
对于级联 PDT,同样适用上述逻辑,但对于级联 PDT:
- 如果未能为一个表构建 PDT,将无法沿依赖项链向下构建 PDT。
- 依赖的 PDT 本质上会查询其依赖的 PDT,因此一个表的持久化策略可能会触发沿链向上重建 PDT。
回顾前面的级联表示例,其中 TABLE_D
依赖于 TABLE_C
,TABLE_C
依赖于 TABLE_B
,TABLE_B
依赖于 TABLE_A
:
如果 TABLE_B
失败,所有标准(非级联)行为都适用于 TABLE_B
:如果查询 TABLE_B
,Looker 会先尝试使用缓存返回结果,在可能的情况下尝试使用旧版表,然后尝试重新构建表,最后如果 TABLE_B
无法重新构建,将返回错误。在下次查询该表或该表的持久化策略下次触发重新构建时,Looker 会再次尝试重新构建 TABLE_B
。
这同样适用于 TABLE_B
的依赖项。因此,如果无法构建 TABLE_B
,并且 TABLE_C
有查询:
- Looker 将尝试在
TABLE_C
上使用缓存进行查询。 - 如果结果不在缓存中,Looker 会尝试从数据库中的
TABLE_C
中提取结果。 - 如果没有有效的
TABLE_C
版本,Looker 会尝试重新构建TABLE_C
,这会在TABLE_B
上创建一个查询。 - 然后,Looker 会尝试重新构建
TABLE_B
(如果TABLE_B
未修复,则会失败)。 - 如果无法重新构建
TABLE_B
,则无法重新构建TABLE_C
,因此 Looker 会针对TABLE_C
上的查询返回错误。 - 然后,Looker 会尝试根据其常规持久化策略重新构建
TABLE_C
,或者在下次查询 PDT 时(包括TABLE_D
下次尝试构建时,因为TABLE_D
依赖于TABLE_C
)。
解决 TABLE_B
的问题后,TABLE_B
和每个依赖表将尝试根据其持久化策略进行重建,或在下次查询它们时(包括从属 PDT 下次尝试重建时)尝试进行重建。或者,如果在开发模式下构建了分级中 PDT 的开发版本,则可以将开发版本用作新的生产 PDT。(如需了解其运作方式,请参阅本页上的开发模式下的永久性表部分。)或者,您也可以使用“探索”对 TABLE_D
运行查询,然后手动重新构建查询的 PDT,这将强制重新构建依赖项级联中的所有 PDT。
提高 PDT 性能
创建永久性派生表 (PDT) 时,性能可能会受到影响。尤其是当表非常大时,查询表的速度可能会很慢,就像数据库中的任何大型表一样。
您可以通过过滤数据或控制 PDT 中数据的排序和编制索引方式来提升性能。
添加过滤条件以限制数据集数量
对于特别大的数据集,拥有很多行会降低针对永久性派生表 (PDT) 的查询速度。如果您通常仅查询最近的数据,请考虑在 PDT 的 WHERE
子句中添加过滤条件,以将表限制为不超过 90 天。这样,每次重新构建表时,系统只会向表中添加相关数据,从而加快运行查询的速度。然后,您可以单独创建一个更大的 PDT 用于历史分析,以便快速查询近期数据和查询旧数据。
使用 indexes
、sortkeys
和 distribution
创建大型永久派生表 (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 上,你可以使用sortkeys
或indexes
,但不能同时使用这两者。 - 在大多数数据库中,请使用
indexes
参数。这些值用于指定将 PDT 的哪些列编入索引。(在 Redshift 上,索引用于生成交错排序键。)