View a markdown version of this page

在亚马逊密钥空间中使用批量语句 - Amazon Keyspaces(Apache Cassandra 兼容)

本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。

在亚马逊密钥空间中使用批量语句

您可以将多个INSERTUPDATE、和DELETE运算组合成一个BATCH语句。LOGGED批次是默认设置。

batch_statement ::= BEGIN [ UNLOGGED ] BATCH [ USING update_parameter( AND update_parameter)* ] modification_statement ( ';' modification_statement )* APPLY BATCH modification_statement ::= insert_statement | update_statement | delete_statement

当您运行批处理语句时,驱动程序会将批处理中的所有语句合并为单个批处理操作。

要决定使用哪种类型的批量操作,可以考虑以下准则。

在以下情况下使用已记录的批次:
  • 你需要原子交易保证。

  • 稍高的延迟是可以接受的折衷方案。

在以下情况下使用未记录的批次:
  • 你需要优化单分区操作。

  • 你想减少网络开销。

  • 您有高吞吐量要求。

有关批处理语句配额的信息,请参阅Amazon Keyspaces(Apache Cassandra 兼容)限额

未记录的批次

对于未记录的批处理,Amazon Keyspaces 将多个操作作为单个请求处理,而无需维护批处理日志。使用未记录的批处理操作,某些操作可能会成功而另一些操作失败。当你想要:时,未记录的批次很有用:

  • 优化单个分区内的操作。

  • 通过对相关请求进行分组来减少网络流量。

未记录批次的语法与已记录批次的语法类似,但添加了UNLOGGED关键字。

BEGIN UNLOGGED BATCH INSERT INTO users (id, firstname, lastname) VALUES (1, 'John', 'Doe'); INSERT INTO users (id, firstname, lastname) VALUES (2, 'Jane', 'Smith'); APPLY BATCH;

记录的批次

记录的批处理将多个写入操作合并为单个原子操作。当你运行已记录的批处理时:

  • 所有行动要么共同成功,要么一起失败。

  • 该操作是同步的,是等效的。

  • 您可以写入多个 Amazon Keyspaces 表,只要它们位于同一个 AWS 账户中,并 AWS 区域且。

记录的批次的延迟可能略高。对于高吞吐量应用程序,可以考虑使用未记录的批处理。

在 Amazon Keyspaces 中使用已记录的批次不会产生额外费用。您只需为批量操作中的写入付费。Amazon Keyspaces 对批次中的每行执行两次基础写入:一次用于为批处理准备该行,另一次用于提交批处理。在为使用记录批次的表规划容量时,请记住,批次中的每行所需的容量是标准写入操作的两倍。例如,如果您的应用程序每秒运行一个记录批处理,其中包含三个 1KB 行,则需要预置六个写入容量单位 (WCU),而单个写入或未记录的批次只配置三个 WCU。

有关定价的信息,请参阅 Amazon Keyspaces(Apache Cassandra 兼容)定价

在记录的批处理中使用预处理语句

记录的批处理支持采用完全原子(全有或全无)执行的预备(绑定)语句。您可以将预处理语句的性能与记录批次的原子性保证相结合。

您可以通过两种方式构造一批已记录的预处理语句。以下示例使用与 Apache Cassandra 兼容的 Java 驱动程序。

在第一种方法中,分别准备每个语句并将绑定语句添加到BatchStatement。此方法支持跨越同一个 AWS 账户中的多个表的批处理,以及 AWS 区域. 以下 Java 代码示例显示了这种方法:

import com.datastax.driver.core.BatchStatement; import com.datastax.driver.core.PreparedStatement; import com.datastax.driver.core.Session; PreparedStatement psInsert = session.prepare( "INSERT INTO my_keyspace.orders (order_id, status) VALUES (?, ?)"); PreparedStatement psUpdate = session.prepare( "UPDATE my_keyspace.inventory SET qty = ? WHERE sku = ?"); BatchStatement batch = new BatchStatement(BatchStatement.Type.LOGGED); batch.add(psInsert.bind(orderId, "CONFIRMED")); batch.add(psUpdate.bind(newQty, sku)); try { session.execute(batch); } catch (Exception e) { // Handle the batch execution error. }

在第二种方法中,将整个BEGIN BATCH ... APPLY BATCH块作为单个语句进行准备,然后绑定并运行它。这种方法最适合其语句针对单个表的批处理。要准备跨多个表的批处理,请使用第一种方法。以下 Java 代码示例显示如何将整个批处理块作为单个语句进行准备:

import com.datastax.driver.core.PreparedStatement; import com.datastax.driver.core.Session; PreparedStatement psBatch = session.prepare( "BEGIN BATCH " + " INSERT INTO my_keyspace.orders (order_id, status) VALUES (?, ?); " + " INSERT INTO my_keyspace.orders (order_id, status) VALUES (?, ?); " + "APPLY BATCH"); try { session.execute(psBatch.bind(orderId1, "CONFIRMED", orderId2, "PENDING")); } catch (Exception e) { // Handle the batch execution error. }

您还可以在记录的批处理中使用带有以下内容的预处理语句:

  • 条件语句(IF NOT EXISTSIF

  • 已命名绑定标记

  • 在同一批中混合使用准备好的和未准备好的语句

  • 在批次中重复使用具有不同绑定值的单个预处理语句

批量操作的最佳实践

使用 Amazon Keyspaces 批量操作时,请考虑以下推荐做法。

  • 启用自动扩展,这样您的表就有足够的吞吐容量来处理批量操作和记录批次的额外吞吐量要求。

  • 当操作可以独立运行而不影响应用程序正确性时,使用单个操作或未记录的批处理。

  • 设计应用程序以最大限度地减少对相同行的并发更新,因为同步批处理操作可能会发生冲突和失败。

  • 对于无需原子性要求的高吞吐量批量数据摄取,请使用单独的写入操作或未记录的批处理。

一致性和并发性

Amazon Keyspaces 对记录的批次强制执行以下一致性和并发性规则:

  • 所有批处理操作都使用LOCAL_QUORUM一致性级别。

  • 影响不同行的并发批处理可以同时执行。

  • 对正在进行的批处理中涉及的行的并发INSERTUPDATE、或DELETE操作因冲突而失败。

支持的运算符和条件

支持的WHERE子句运算符:
  • 平等 (=)

不支持的运算符:
  • 范围运算符(>、<、>=、<=)

  • IN 运算符

  • LIKE 运算符

  • BETWEEN 运算符

记录的批次不支持:
  • 影响同一行的多个语句

  • 反击行动

  • 范围删除

通过指定具有相等条件的完整主键(所有分区键和聚类列),记录的批处理中的DELETE语句必须以单行为目标。记录的批处理不支持范围删除,例如单独按分区键删除或跨一系列群集列删除。要运行范围删除,请使用独立DELETE语句或未记录的批处理。

记录的批处理语句的失败条件

在以下任何情况下,记录的批处理操作都可能失败:

  • 条件表达式(如IF NOT EXISTSIF)的计算结果为假。

  • 一个或多个操作包含无效的参数。

  • 该请求与在同一行上运行的另一个批处理操作冲突。

  • 该表缺少足够的预置容量。

  • 一行超过了最大大小限制。

  • 输入数据格式无效。

批量语句和多区域复制

在多区域部署中:

  • 源区域操作是同步的和原子的。

  • 目标区域操作是异步的。

  • 所有批处理操作都会复制到目标区域,但在应用程序期间可能无法保持隔离。

监控批量操作

您可以使用亚马逊 CloudWatch 指标监控批量操作,以跟踪性能、错误和使用模式。Amazon Keyspaces 提供以下 CloudWatch 指标来监控每个表的批量操作:

  • SuccessfulRequestCount— 跟踪成功的批量操作。

  • Latency— 衡量批量操作性能。

  • ConsumedWriteCapacityUnits— 监控批处理操作的容量消耗。

有关更多信息,请参阅 Amazon Keyspaces 指标

除了 CloudWatch 指标外,您还可以使用 AWS CloudTrail 来记录所有亚马逊 Keyspaces API 操作。批次中的每个 API 操作都会记录在 CloudTrail 案,这样可以更轻松地跟踪和审计 Amazon Keyspaces 表中的批量操作。

批量操作示例

以下是基本的已记录批处理语句的示例。

BEGIN BATCH INSERT INTO users (id, firstname, lastname) VALUES (1, 'John', 'Doe'); INSERT INTO users (id, firstname, lastname) VALUES (2, 'Jane', 'Smith'); APPLY BATCH;

这是包含INSERTUPDATE、和DELETE语句的批处理示例。

BEGIN BATCH INSERT INTO users (id, firstname, lastname) VALUES (1, 'John', 'Doe'); UPDATE users SET firstname = 'Johnny' WHERE id = 2; DELETE FROM users WHERE id = 3; APPLY BATCH;

这是使用客户端时间戳的批处理示例。

BEGIN BATCH INSERT INTO users (id, firstname, lastname) VALUES (1, 'John', 'Stiles') USING TIMESTAMP 1669069624; INSERT INTO users (id, firstname, lastname) VALUES (2, 'Jane', 'Doe') USING TIMESTAMP 1669069624; APPLY BATCH; BEGIN BATCH UPDATE users USING TIMESTAMP 1669069624 SET firstname = 'Carlos' WHERE id = 1; UPDATE users USING TIMESTAMP 1669069624 SET firstname = 'Diego' WHERE id = 2; APPLY BATCH;

这是条件批处理的示例。

BEGIN BATCH INSERT INTO users (id, firstname, lastname) VALUES (1, 'Jane', 'Doe') IF NOT EXISTS; INSERT INTO users (id, firstname, lastname) VALUES (2, 'John', 'Doe') IF NOT EXISTS; APPLY BATCH; BEGIN BATCH UPDATE users SET lastname = 'Stiles' WHERE id = 1 IF lastname = 'Doe'; UPDATE users SET lastname = 'Stiles' WHERE id = 2 IF lastname = 'Doe'; APPLY BATCH;

这是使用生存时间 (TTL) 进行批处理的示例。

BEGIN BATCH INSERT INTO users (id, firstname, lastname) VALUES (1, 'John', 'Doe') USING TTL 3600; INSERT INTO users (id, firstname, lastname) VALUES (2, 'Jane', 'Smith') USING TTL 7200; APPLY BATCH;

这是更新多个表的批处理语句的示例。

BEGIN BATCH INSERT INTO users (id, firstname) VALUES (1, 'John'); INSERT INTO user_emails (user_id, email) VALUES (1, 'john@example.com'); APPLY BATCH;

这是使用用户定义类型 (UDT) 的批量操作的示例。该示例假定 UDT address 存在。

BEGIN BATCH INSERT INTO users (id, firstname, address) VALUES (1, 'John', {street: '123 Main St', city: 'NYC', zip: '10001'}); INSERT INTO users (id, firstname, address) VALUES (2, 'Jane', {street: '456 Oak Ave', city: 'LA', zip: '90210'}); APPLY BATCH; BEGIN BATCH UPDATE users SET address.zip = '10002' WHERE id = 1; UPDATE users SET address.city = 'Boston' WHERE id = 2; APPLY BATCH;