mcpField
Y
ycql

ycql

github.com/yugabyte数据与数据库946 次安装1 周前更新
代码仓库

关于 ycql

ycql 是一项 YugabyteDB YCQL 最佳实践技能,面向数据库开发者,涵盖模式设计、查询优化和运行配置。

主要功能

  1. 01分区键与聚簇列设计
  2. 02全局及覆盖索引建议
  3. 03数据类型与容量限制
  4. 04TTL 与一致性级别说明
  5. 05查询、批处理与重试优化
  6. 06大表扫描及清理建议

适用场景

  1. 01规划订单等表的分区和排序
  2. 02为常用查询选择索引与语句
  3. 03配置数据过期和读取一致性
  4. 04优化批处理及大型表扫描

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/yugabyte/yugabytedb-skills --skill ycql

安装后在 Claude Code 中输入/ycql确认已加载。

详细介绍

YugabyteDB YCQL 最佳实践

YCQL 是 YugabyteDB 与 Cassandra 兼容的 API(端口 9042)。它提供具有强一致性(ACID)的全局二级索引,这是相较于 Apache Cassandra 的一项关键优势。

模式设计

分区键和聚簇列

设计分区键以实现均匀的数据分布,并设计聚簇列以便在分区内高效进行范围扫描:

CREATE TABLE orders (
    customer_id UUID,
    order_date TIMESTAMP,
    order_id UUID,
    total DECIMAL,
    PRIMARY KEY ((customer_id), order_date DESC, order_id)
) WITH CLUSTERING ORDER BY (order_date DESC, order_id ASC);
  • 分区键(customer_id):决定平板的放置位置。应选择能实现均匀分布的键。
  • 聚簇列(order_date、order_id):决定分区内的排序顺序。
全局二级索引

YugabyteDB 中的 YCQL 二级索引是全局且强一致的(ACID),不同于 Cassandra 的本地索引:

CREATE INDEX idx_orders_date ON orders (order_date);
覆盖索引

使用 INCLUDE 子句直接从索引提供查询结果,无需查找表:

CREATE INDEX idx_orders_customer ON orders (customer_id) INCLUDE (total, order_date);
唯一索引
CREATE UNIQUE INDEX idx_users_email ON users (email);

数据类型

  • **JSONB:**支持无模式数据,但仅用于真正动态的值。对于频繁访问的模式,常规列的性能优于 JSONB。
  • **计数器递增:**YugabyteDB 支持使用 CAS 操作在一次 Raft 往返中递增或递减整数(Apache Cassandra 中需要 4 次)。
  • **集合:**应针对小型数据集进行设计。大型集合会显著影响性能。

大小限制

  • **列:**保持在 2 MB 左右或更小
  • **行:**保持在 32 MB 左右或更小

TTL(生存时间)

可在表、行或列级别自动使数据过期:

-- Table-level TTL
CREATE TABLE events (
    id UUID PRIMARY KEY,
    data TEXT
) WITH default_time_to_live = 86400;  -- 24 hours

-- Row-level TTL on insert
INSERT INTO events (id, data) VALUES (uuid(), 'event data') USING TTL 3600;

-- Column-level TTL
UPDATE events USING TTL 7200 SET data = 'updated' WHERE id = ?;

**注意:**事务表不支持 TTL。

一致性级别

YugabyteDB YCQL 仅支持两个一致性级别:QUORUM(默认)和 ONE。写入始终具有强一致性(QUORUM)。使用 ONE 进行追随者读取(从最近的副本读取可能过时但延迟较低的数据)。

// Default: QUORUM (strong consistency)
Statement stmt = SimpleStatement.newInstance("SELECT * FROM orders WHERE customer_id = ?", id)
    .setConsistencyLevel(ConsistencyLevel.ONE); // Read from nearest replica (may be stale)

轻量级事务(原子化读取-修改-写入)

IF EXISTS / IF NOT EXISTS 操作比 Apache Cassandra 快得多:只需 1 次 Raft 往返,而 LWT 需要 4 次 Raft 往返:

-- Atomic insert-if-not-exists
INSERT INTO users (id, email, name) VALUES (?, ?, ?) IF NOT EXISTS;

-- Atomic conditional update
UPDATE accounts SET balance = ? WHERE id = ? IF balance >= ?;

查询优化

预处理语句(始终使用)

预处理语句支持分区感知路由:驱动程序会计算分区哈希,并将查询直接发送到正确的平板 Leader:

PreparedStatement ps = session.prepare("SELECT * FROM orders WHERE customer_id = ?");
BoundStatement bs = ps.bind(customerId);
session.execute(bs);
批处理

批处理操作会在单次 RPC 调用中发送所有操作:

BatchStatement batch = BatchStatement.newInstance(DefaultBatchType.UNLOGGED);
batch = batch.add(ps1.bind(...));
batch = batch.add(ps2.bind(...));
session.execute(batch);

为获得最佳性能,应使用批处理将目标为同一分区的操作分组。

连接池

使用单个集群对象管理连接。对于 64–128 个线程,每个 YB-TServer 通常 1–2 个连接就足够。使用预处理语句时,驱动程序会自动处理令牌感知路由。

重试策略

默认重试策略会在某些故障时重试一次。对于写入密集型工作负载,可配置带退避机制的自定义重试策略,以应对负载均衡期间平板 Leader 的短暂变更。

大型表操作

使用 partition_hash 将扫描并行分发到各个平板:

SELECT * FROM large_table WHERE partition_hash(id) >= 0 AND partition_hash(id) < 5000;
SELECT * FROM large_table WHERE partition_hash(id) >= 5000 AND partition_hash(id) < 10000;

TRUNCATE 与 DELETE

TRUNCATE 比 DELETE 快得多。DELETE 会插入标记(墓碑),需要进行压缩。清理整张表时应使用 TRUNCATE。

内存配置

对于仅部署 YCQL 的环境,在 yb-master 上设置 --use_memory_defaults_optimized_for_ysql=false,以避免为 PostgreSQL 层预留内存。

评论

支持 Markdown