【问题标题】:YCQL Secondary indexes on tables with TTL in YugabyteDBYugabyteDB中带有TTL的表的YCQL二级索引
【发布时间】:2021-12-22 04:16:55
【问题描述】:

[用户在YugabyteDB Community Slack上发布的问题]

我有一个带有 TTL 和二级索引的表,使用 YugabyteDB 2.9.0,当我尝试插入一行时出现以下错误:

SyntaxException: Feature Not Supported

以下是我的架构:

CREATE TABLE lists.list_table (
    item_value text,
    list_id uuid,
    created_at timestamp,
    updated_at timestamp,
    is_deleted boolean,
    valid_from timestamp,
    valid_till timestamp,
    metadata jsonb,
    PRIMARY KEY ((item_value, list_id))
) WITH default_time_to_live = 0
    AND transactions = {'enabled': 'true'};

CREATE INDEX list_created_at_idx ON lists.list_table (list_id, created_at)
WITH transactions = {'enabled': 'true'};

我们有两种类型的查询(80% 和 20% 分布):

select * from list_table where list_id= <id> and item_value = <value> 
select * from list_table where list_id= <id> and created_at>= <created_at>

我们预计每个list_id 将有大约 1000-10000 个条目。 TTL 大约是 1 个月。

【问题讨论】:

    标签: yugabyte-db


    【解决方案1】:

    这是一个限制,目前不支持使用 TTL 从已索引的表中以事务方式使行过期(即表和索引中的 TTL 条目的原子过期)。有几种解决方法:

    a) 在 YCQL 中,我们还支持一致性较弱的索引。今天没有很好的记录,但您可以在此处查看详细信息:https://github.com/YugaByte/yugabyte-db/issues/1696

    使用这种索引变体时要注意的主要问题是错误处理(在 INSERT 失败时),即在失败时重试 INSERT 是应用程序端的责任。如上述问题中所述 >

    这种类型的索引支持表和索引级别的 TTL。 (建议保持不变):https://github.com/yugabyte/yugabyte-db/issues/2481#issuecomment-537177471

    b)另一种解决方法是使用后台清理作业定期删除过时的记录(而不是使用 TTL)。

    c)避免使用索引并将数据存储在两个表中。一个由原始主键组织,一个由您想要的索引列组织(作为主键)。两个表都可以有 TTL。但是当数据被添加到数据库中时,插入两个表是应用程序端的责任。

    第一个表的 PK 为 ((list_id, item_value)),与当前主表相同。您将拥有第二张表,而不是索引;第二个表的 PK 将是 ((list_id), created_at) 并且两个表都有一个 TTL。应用程序必须将数据插入到两个表中。在第二张表中,您可以选择: (选项 1)在此处复制主表中的所有列,包括您的 JSON 列等。这使 Q2 查找速度更快,该行具有所需的一切;但会增加您的存储需求。 (选项2):除了PK,只把item_value列存到第二张表中。对于第二季度,您必须首先查找第二张表并获取 item_value,然后使用 list_id 和 item_value 从主表中检索数据(就像索引在幕后所做的那样)。

    d)另一种解决方法是,如果我们可以避免索引并选择 PK 为 ((list_id, item_value), created_at)

    这不会影响 Q1 的性能,因为使用(where list_id and item_value) 可以使用 PK 查找行。但是提供第二季度where list_id and created_at 会慢一些,因为虽然它仍然可以使用list_id,但它必须在没有索引帮助的情况下使用created_at 值过滤掉数据。因此,如果 Q2 确实占您查询的 20%,您可能不想扫描 1 到 10k 个项目来查找匹配行。

    为了阐明选项 (c),请记住以下示例: 第一个表的 PK 将是 ((list_id, item_value));它与您当前的主表相同。您将拥有第二个表,而不是索引;第二个表的 PK 将是 ((list_id), created_at)。 两个表都有一个 TTL 应用程序必须将条目插入到两个表中。 在第二张表中,您可以选择: (选项 1)复制主表中的所有列,包括您的 JSON 列等。这使 Q2 查找速度更快,该行具有所需的一切;但会增加您的存储需求。 (选项2):除了Primary Key,只在第二张表中存储item_value列。对于 Q2,您必须首先查找第二张表并获取 item_value,然后使用 list_id 和 item_value 从主表中检索数据(就像索引在幕后所做的那样)

    【讨论】:

      猜你喜欢
      • 2021-12-22
      • 2022-10-13
      • 2022-06-15
      • 2022-01-26
      • 2022-07-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-07-25
      相关资源
      最近更新 更多