混合表的最佳实践

本主题介绍使用混合表的最佳实践和重要注意事项。要使用混合表实现最佳性能,请在部署中遵循这些最佳实践。本指南概述了可最大限度地提高生产工作负载性能的具体配置、设计和操作实践。

Snowsight 中的查询性能与基于驱动程序的访问性能对比

注意

Snowsight 中报告的性能统计数据并不代表基于驱动程序的工作负载的查询性能。

Snowsight 提供了对查询计划、数据统计、查询历史记录和其他详细信息的丰富访问权限,这些信息对于交互式查询原型、调试、调查、监控和其他活动非常有用。提供丰富的交互体验会增加 Snowflake 查询引擎的开销。因此,通过 Snowsight 执行的短期运行查询的延迟并不表示使用程序驱动程序可以实现的性能。通过基于代码或基于驱动程序的解决方案执行的查询,相比通过 Snowsight 执行的查询,具有更低的延迟和更稳定的性能。

备注

运行 简单的性能测试,以验证您的场景性能。

混合表的客户端驱动程序

要访问混合表,您需要使用以下驱动程序版本:

驱动程序

最低版本

Go

1.6.25

JDBC

3.13.31

.Net

2.1.2

Node.js

1.9.0

ODBC

3.0.2

PHP

2.0.0

Python Connector

3.1.0

Snowflake CLI

3.10.0

SnowSQL

1.2.28

备注

您可能无法使用更早版本的驱动程序访问混合表。

要使用混合表获得最佳性能,请务必使用所选驱动程序的最新版本。

您也可以通过使用 Snowflake SQL API 访问混合表;但是,对于需要最佳延迟的用例,不推荐使用 API。

客户端配置和访问方法

连接管理直接影响性能和可扩展性。当连接到包含混合表的数据库时,请考虑以下最佳实践以实现良好的性能。

  • 将连接池与长效连接结合使用,以消除重复建立新连接的开销。大多数连接到 Snowflake 的客户端框架都提供连接池机制来高效管理访问。

  • 网络接近性显著影响端到端延迟;因此,请使客户端软件与 Snowflake 账户位于同一云区域。

  • 使用带绑定参数的预处理语句,以便查询规划器重用以前创建的查询计划。

  • 使用支持的编程客户端驱动程序(而不是 Snowsight),以达到最佳延迟。请参阅 混合表的客户端驱动程序

索引设计和使用

创建和使用索引是实现混合表最佳性能的关键组件。请考虑以下建议:

  • 为频繁使用的谓词创建辅助索引。

  • 设计复合索引以匹配完整的查询模式。

  • 避免在相同序位的列上使用多个索引。

  • 在创建索引之前了解数据的基数。用单个低基数列构建的索引的好处有限。请参阅 估计非重复值的数量

  • 索引增加了写入开销和存储要求。对于需要低延迟写操作的应用程序,要注意平衡读写性能。

合理设计的索引通过提供高效的数据访问路径,显著提高查询性能。如果可能,选择主键以获得最佳选择性,同时尽可能降低复杂性。在某些情况下,相比复杂的复合索引,添加具有计算或替代键值的列会提供更佳的性能。辅助索引可显著提高频繁访问列的性能。

对于定义明确的查询,在创建表时使用 INCLUDE 关键字向索引中添加列可能会进一步减少延迟。请参阅 INCLUDE 列

注意

请注意在混合表上创建的索引;非选择性索引扫描会导致次优性能、节流和更高的成本。

符合索引使用的查询

当查询使用以下条件之一时,可以访问混合表索引:

  • <column_reference> {=, >, >=, <, <=} <constant_value>

  • <column_reference> IN <constant_in_list>

  • <column_reference> BETWEEN <constant_value> AND <constant_value>

可以使用 逻辑运算符 将表达式链接在一起。

例如:

CREATE OR REPLACE HYBRID TABLE icecream_orders (
  id NUMBER PRIMARY KEY AUTOINCREMENT START 1 INCREMENT 1 ORDER,
  store_id NUMBER NOT NULL,
  flavor VARCHAR(20) NOT NULL,
  order_ts TIMESTAMP_NTZ,
  num_scoops NUMERIC,
  INDEX idx_icecream_order_store (store_id, order_ts),
  INDEX idx_icecream_timestamp (order_ts)
  );

-- Generate sample data for testing

INSERT INTO icecream_orders (store_id, flavor, order_ts, num_scoops)
  SELECT
    UNIFORM(1, 10, RANDOM()),
    ARRAY_CONSTRUCT('CHOCOLATE', 'VANILLA', 'STRAWBERRY', 'LEMON')[UNIFORM(0, 3, RANDOM())],
    DATEADD(SECOND, UNIFORM(0, 86400, RANDOM()), DATEADD(DAY, UNIFORM(-90, 0, RANDOM()), CURRENT_DATE())),
    UNIFORM(1, 3, RANDOM())
  FROM TABLE(GENERATOR(ROWCOUNT => 10000))
  ;

-- Use idx_icecream_order_store (first column)

  SELECT *
    FROM icecream_orders
    WHERE store_id = 5;

-- Use idx_icecream_order_store (both columns)

  SELECT *
    FROM icecream_orders
    WHERE store_id IN (1,2,3) AND order_ts > DATEADD(DAY, -7, CURRENT_DATE());

-- Use idx_icecream_timestamp

  SELECT *
    FROM icecream_orders
    WHERE order_ts BETWEEN DATEADD(DAY, -2, CURRENT_DATE()) AND DATEADD(DAY, -2, CURRENT_DATE());
Copy

Foreign keys for join queries

In general, queries that require joins benefit from the definition of FOREIGN KEY constraints. Although foreign keys aren't required for running hybrid table queries, they do assist the optimizer in building the most effective query plan. Foreign keys provide two important functions:

  • They establish referential integrity between tables.

  • They provide the query planner with metadata for optimization.

A FOREIGN KEY constraint informs the query optimizer that a particular record in a child table points to exactly one record in a parent table. This behavior is one way in which query predicates are "pushed down" during a join, thereby optimizing storage I/O. The query is executed as a "one-to-many" join. Joining hybrid tables without foreign keys means that they are executed as "many-to-many" joins, such that additional query predicates might be necessary to optimize the query.

For more information, see the following topics:

批量加载数据

您可以使用几种优化和最佳实践将数据加载到混合表:

混合表提供了优化的批量加载路径,其加载性能比标准加载方法快多达 10 倍。当使用 CTAS (CREATE TABLE AS SELECT)、COPY INTO 或 INSERT INTO SELECT 命令将数据加载到空表中时,将自动应用此优化的批量加载路径。(空表是指从未包含任何数据的表。)

您可以通过检查查询配置文件的统计部分来验证是否在使用优化,其中行将报告为 Number of rows bulk loaded``(而不是 ``Number of rows inserted)。

备注

CTAS 操作不支持 FOREIGN KEY 约束。如果表需要外键,则必须改用 COPY 或 INSERT INTO SELECT。

对于已包含数据的表,优化的批量加载路径目前不可用。在这些情况下,加载操作可能达到每分钟大约 100 万条记录,但这会因记录大小、表结构和索引数量而有所不同。

仓库优化

X-Small 大小的仓库足以满足众多运算工作负载的需求。为使短期运行的运算查询实现更高的并发性和吞吐量,请使用 多群集仓库 来增加计算节点,而不是使用更大的仓库来增加计算资源。

如果工作负载具有可变吞吐量模式,则可以启用自动缩放,以便在需求较低时减少消耗。将扩展策略设置为 Standard 而不是 Economy,以便需要高吞吐量或低延迟的工作负载实现最佳性能和效率。有关更多信息,请参阅 为多集群仓库设置扩展策略

在某些情况下,将工作负载隔离在单独的仓库中可能有利于实现独立扩展。如果您有包含运算和分析组件的混合工作负载,则将运算和分析组件分隔在不同的仓库中会很有帮助。如果无法分隔它们,并且必须在同一仓库上一起执行它们,则根据分析查询延迟要求选择仓库大小,并根据工作负载吞吐量支持需求选择多群集节点数。

缓存和预热

向新启动的仓库发出的第一个混合表查询会触发查询规划、索引选择、加载数据的 I/O、缓存决策以及查询执行等活动。查询引擎继续为查询优化内存和存储。这段时间称为“预热”期。查询延迟逐渐降低,直到引擎收敛到稳态延迟。

  • 使用专用仓库处理混合表工作负载,以避免缓存干扰。

  • 了解达到稳态延迟需要几秒钟到 2 至 3 分钟,因为缓存会预热。

  • 配置自动挂起和自动扩展以平衡效率和缓存预热。

混合表利用多种缓存方法来优化性能。计划缓存通过存储频繁使用的查询计划来减少编译开销。列存储数据缓存在内存中维护频繁访问的数据,元数据缓存提供对表和索引信息的快速访问。混合表不使用结果缓存。

这些缓存需要一些时间来针对工作负载模式进行优化。将专用仓库用于混合表工作负载可以防止来自其他工作负载的缓存干扰。冷启动后的初始查询在填充缓存之前会经历更高的延迟。如果工作负载具有变量吞吐量模式,则可以启用自动扩展和自动挂起以减少消耗,或在需求较低时挂起仓库。当仓库重新启动或自动扩展以添加新集群时,缓存将需要重新水化。将扩展策略设置为 Standard``(而不是 ``Economy)以获得最佳性能。请参阅 多集群仓库

存储过程和混合表

混合表支持存储过程;但是相较于调用存储过程,执行已启用 AUTOCOMMIT 的事务或多语句事务可以提供更好的性能和效率。

无服务器任务和混合表

虽然支持无服务器任务,但请注意,对于使用混合表的工作负载,您可能无法体验出色的性能或效率。

性能监控

推荐用于混合表性能监控的视图是 AGGREGATE_QUERY_HISTORY 视图。此视图包含在短时间内聚合的查询执行详细信息。

例如,要检索为混合表请求提供服务的仓库在过去 24 小时内的平均默认间隔性能,请执行以下操作:

SELECT *
  FROM SNOWFLAKE.ACCOUNT_USAGE.AGGREGATE_QUERY_HISTORY
  WHERE warehouse_name = 'HYBRID_TABLES_WAREHOUSE'
  AND query_type = 'SELECT'
  AND interval_start_time >= DATEADD(hour, -24, CURRENT_TIMESTAMP());
Copy

有关更多示例,请参阅 AGGREGATE_QUERY_HISTORY 视图

监控配额和节流

混合表在数据库级别对混合存储和混合表请求吞吐量实施配额控制。这些配额确保所有用户的性能一致。对于大多数初始实施,默认配额已经足够,但随着工作负载的增长,可能需要进行调整。

  • 使用 AGGREGATE_QUERY_HISTORY 视图 监控混合表请求配额。

  • 使用 STORAGE_USAGE 视图 监控混合存储配额。

  • 查询配置文件中的高节流百分比表示您正在接近吞吐量限制。当您始终使用任一配额的 70% 以上时,请通过 Snowflake 支持部门主动请求增加配额。

即使在虚拟仓库计算使用量不高的情况下,混合表的性能也受到节流的影响。要监控使用量并确定混合表是否正在节流,请参阅 AGGREGATE_QUERY_HISTORY 视图 中的示例。您还可以从 HYBRID_TABLE_REQUESTS_THROTTLED_COUNT 列检索节流混合表请求的数量。

有关更多信息,请参阅 配额和节流

排除性能问题

如果您在实施这些最佳实践后没有达到预期的性能,Snowflake 支持部门可帮助分析和优化您的实施。创建支持案例时,请添加以下信息,以便快速解决:

  • 查询 IDs (UUIDs),用于显示次优性能的代表性查询

  • 工作负载特性:

    • 典型查询模式

    • 预期延迟与实际延迟

    • 并发性要求

    • 数据存储卷

    • 查询响应行大小

    • 基数估计值

  • 最近对表架构、索引或工作负载模式的任何更改

  • 查询配置文件中的节流指标

  • 冷库和暖库的性能差异

如果可能,添加类似查询的快速和缓慢示例,以帮助确定优化机会。这种比较有助于支持团队快速确定潜在的配置或设计改进方面。

语言: 中文