在 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 术语定义的查询。如需创建原生派生表,请在 view 参数的 derived_table
参数内使用 explore_source
参数。您可以通过引用模型中的 LookML 维度或测量来创建原生派生表的列。请参阅上一个示例中的原生派生表视图文件。
与基于 SQL 的派生表相比,在对数据建模时,原生派生表更易于阅读和理解。
如需详细了解如何创建原生派生表,请参阅创建原生派生表文档页面。
基于 SQL 的派生表
如需创建基于 SQL 的派生表,请使用 SQL 术语定义查询,并使用 SQL 查询在表中创建列。您不能在基于 SQL 的派生表中引用 LookML 维度和测量值。请参阅上一个示例中基于 SQL 的派生表视图文件。
最常见的做法是使用 view 参数的 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
参数(而不是sql
参数)来创建 PDT。如需了解相关信息和示例,请参阅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 | 是 |
迪诺多 7 | 是 |
迪诺多 8 号星 | 是 |
德雷米奥 | 是 |
Dremio 11+ | 是 |
Exasol | 是 |
火箭 | 是 |
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 数据库用户配置具有写入权限的架构。
- 配置了启用 PDT 切换开关的 Looker 连接。这通常是在首次配置 Looker 连接时设置的(如需了解数据库方言的说明,请参阅 Looker 方言文档页面),但您也可以在初始设置后为连接启用 PDT。
PDT 支持的数据库方言
为了让 Looker 在 Looker 项目中支持永久性派生表 (PDT),您的数据库方言也必须支持 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 | 是 |
迪诺多 7 | 否 |
迪诺多 8 号星 | 否 |
德雷米奥 | 否 |
Dremio 11+ | 否 |
Exasol | 是 |
火箭 | 否 |
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 | 是 |
迪诺多 7 | 否 |
迪诺多 8 号星 | 否 |
德雷米奥 | 否 |
Dremio 11+ | 否 |
Exasol | 是 |
火箭 | 否 |
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 是一种永久性派生表 (PDT),Looker 通过向表附加新数据(而不是完整重新构建表)来构建该表。
如果您的方言支持增量 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 | 是 |
迪诺多 7 | 否 |
迪诺多 8 号星 | 否 |
德雷米奥 | 否 |
Dremio 11+ | 否 |
Exasol | 否 |
火箭 | 否 |
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 管理,对于支持具体化视图的方言,可以通过数据库使用具体化视图来管理。
如需使派生表持久化,请将以下参数之一添加到 derived_table
定义中:
- Looker 管理的持久性参数: <ph type="x-smartling-placeholder">
- 数据库管理的持久性参数:
<ph type="x-smartling-placeholder">
- </ph>
materialized_view: yes
使用基于触发器的持久化策略(datagroup_trigger
、sql_trigger_value
和 interval_trigger
)时,Looker 会在数据库中维护 PDT,直到系统触发用于重建的 PDT。触发 PDT 后,Looker 会重建 PDT 以替换之前的版本。这意味着,使用基于触发器的 PDT,您的用户无需等待构建 PDT,即可从 PDT 获得与“探索”类查询相关的答案。
datagroup_trigger
数据组是创建持久性的最灵活方法。如果您使用 sql_trigger
或 interval_trigger
定义了数据组,则可以使用 datagroup_trigger
参数开始重建永久性派生表 (PDT)。
Looker 会在数据库中维护 PDT,直到其数据组被触发。触发数据组后,Looker 会重建 PDT 以替换之前的版本。这意味着在大多数情况下,您的用户无需等待构建 PDT。如果用户在构建 PDT 时从 PDT 请求数据,并且查询结果不在缓存中,则 Looker 将从现有 PDT 返回数据,直到构建新的 PDT。如需简要了解数据组,请参阅缓存查询。
如需详细了解该重新生成器如何构建 PDT,请参阅 Looker 再生成器部分。
sql_trigger_value
sql_trigger_value
参数会根据您提供的 SQL 语句触发重新生成永久性派生表 (PDT)。如果 SQL 语句的结果与先前的值不同,系统会重新生成 PDT。否则,现有的 PDT 会保留在数据库中。这意味着在大多数情况下,您的用户无需等待构建 PDT。如果用户在构建 PDT 时从 PDT 请求数据,并且查询结果不在缓存中,则 Looker 将从现有 PDT 返回数据,直到构建新的 PDT。
如需详细了解该重新生成器如何构建 PDT,请参阅 Looker 再生成器部分。
interval_trigger
interval_trigger
参数会根据您提供的时间间隔(例如 "24 hours"
或 "60 minutes"
)触发系统重新生成永久性派生表 (PDT)。与 sql_trigger
参数类似,这意味着,当用户查询 PDT 时,系统通常会预先构建 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 时重新构建该 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 连接配置了启用 PDT 切换开关,您可以通过为派生表指定 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 可能会受到其依赖项的持久性策略的影响。
为查询手动重建永久性表
用户可以选中“Rebuild Derived Tables &”运行选项,以覆盖保留设置并重新构建“探索”中的当前查询所需的所有永久性派生表 (PDT) 和汇总表:
此选项仅对拥有 develop
权限的用户显示,且只有在“探索”查询加载完成后。
重新构建派生表和运行选项会重建回答查询所需的所有永久性表(所有 PDT 和汇总表),而无论其持久性策略如何。这包括当前查询中的所有汇总表和 PDT,以及当前查询中的汇总表和 PDT 引用的所有汇总表和 PDT。
对于增量 PDT,请参阅重新构建派生表和Run 选项触发新增量的构建。使用增量 PDT 时,增量包括 increment_key
参数中指定的时间段,以及 increment_offset
参数中指定的先前时间段的数量(如果有)。请参阅增量 PDT 文档页面,查看一些示例场景,了解增量 PDT 如何根据其配置进行构建。
对于级联 PDT,这意味着从顶部开始重新构建级联中的所有派生表。这与在临时派生表级联中查询表时的行为相同:
关于手动重建派生表,请注意以下几点:
- 对于启动重新构建派生表并Run 操作时,查询会等待表重建,然后再加载结果。其他用户的查询仍将使用现有表。永久性表重建后,所有用户都将使用重建的表。尽管这一流程旨在避免干扰其他用户的查询,那么这些用户仍可能会受到数据库额外负载的影响。如果您在工作时间触发重新构建操作会给数据库带来不可接受的压力,则可能需要告知用户,他们绝不应在这些时间内重新构建某些 PDT 或汇总表。
如果用户处于开发模式,并且探索基于开发表,重新构建派生表和Run 操作将为“探索”重新构建开发表,而不是生产表。但是,如果“开发模式下的探索”使用的是派生表的生产版本,则将重新构建生产表。如需了解开发表和生产表,请参阅开发模式下的持久保留表。
对于 Looker 托管的实例,如果派生表的重建时间超过 1 小时,则该表将无法成功重建,并且浏览器会话将会超时。如需详细了解可能会影响 Looker 进程的超时,请参阅管理设置 - 查询文档页面的查询超时和队列部分。
在开发模式下保留的表
Looker 在开发模式下管理持久化表时有一些特殊行为。
如果您在开发模式下查询持久化表,而未对其定义进行任何更改,则 Looker 将查询该表的生产版本。如果您确实更改了表定义,而所做更改会影响表中的数据或表的查询方式,那么您下次在开发模式下查询表时,系统会创建表的新开发版本。有了这样的开发表格,您就可以在不干扰最终用户的情况下测试更改。
促使 Looker 创建开发表的因素
无论您是否处于开发模式,Looker 都会尽可能使用现有的生产表来回答查询。但在某些情况下,Looker 无法使用生产表在开发模式下执行查询:
- 如果持久化表的参数将其数据集范围缩小以在开发模式下运行更快
- 您对持久性表的定义进行了更改,而这些更改会影响表中的数据
如果您处于开发模式,并且查询基于 SQL 的派生表,Looker 会构建一个开发表,该表使用包含 if prod
和 if dev
语句的条件 WHERE
子句进行定义。
对于在开发模式下没有用于缩小数据集范围的保留表,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 创建开发表的因素部分。
因此,最好在部署到生产环境时构建所有 PDT,以便可以立即将表用作生产环境版本。
您可以在 Project Health 面板中检查项目是否存在未构建的 PDT。点击 Looker IDE 中的 Project Health 图标,以打开 Project Health 面板。然后点击验证 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
在表的开发版本的优先级更高。在此示例中,表格的开发版本会过滤出尤卡山谷机场过去 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 维护时间表设置中配置(默认为五分钟间隔)。
以下几个因素会影响重新构建表所需的时间:
- 您的 Looker 管理员可能使用数据库连接的数据组和 PDT 维护时间表设置更改了重新生成器触发器检查的间隔。
- 在完成上一个周期的所有检查和 PDT 重建之前,Looker 重新生成器不会启动新周期。因此,如果您有长时间运行的 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 将使用缓存中的结果。(有关其工作原理的说明,请参阅缓存查询文档页面。)
- 如果结果不在缓存中,并且存在有效的 PDT 版本,Looker 将从数据库中的 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
:如果查询 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 会根据其常规保留策略或下次查询 PDT 时(包括
TABLE_D
下次尝试构建的时间,因为TABLE_D
依赖于TABLE_C
)尝试重新构建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 上,索引用于生成交错排序键。)