Cassandra 使用二级索引按日期过滤

Posted

技术标签:

【中文标题】Cassandra 使用二级索引按日期过滤【英文标题】:Cassandra filtering by date with a secondary index 【发布时间】:2014-12-16 08:57:12 【问题描述】:

我需要回答以下问题:

返回每季度(最长 36 个月)的新客户数量 列出每季度(最长 36 个月)的新客户

我在 Cassandra 中创建了下表来处理这个问题:

CREATE TABLE first_purchase_by_shopper_date
(
    shop_id                     uuid,
    shopper_id                  uuid,
    dt_first_purchase           timestamp,

    ... (some text fields)

    PRIMARY KEY ((shop_id, shopper_id))
);

为了能够在 Cassandra 中回答此查询,我需要能够在 dt_first_purchase 字段中过滤此数据。

但是,如果我将 dt_first_purchase 添加到主键,那么它会使该行对购物者来说是非唯一的 - 因此我们会在表中获得多个条目 - 但我们只想要 每个购物者一个条目。

所以我的插入语句看起来像

Insert into first first_purchase_by_shopper_date (shop_id, shopper_id, dt_first_purchase, ... ) Values(...) If Not Exists;

最后的 if not exists 确保只有在不存在条目时才写入条目(例如,不对现有记录执行更新。)

如何在此表上按日期过滤 - dt_first_purchase 列上的二级索引是我唯一的选择 - 这不是不可取的吗?

【问题讨论】:

【参考方案1】:

如何在此表上按日期过滤 - 是 dt_first_purchase 列是我唯一的选择 - 这不是不可取的吗?

您当然可以在dt_first_purchase 上尝试二级索引(并且按范围查询也需要使用ALLOW FILTERING 指令)。出于性能考虑(尤其是大型集群),我不建议这样做。

但首先,要了解 Cassandra 的设计目的是为特定数据分区上的特定键返回数据。这意味着您按日期范围查询数据的最佳方法是首先按对您的模型有意义的键对数据进行分区。例如,如果你有一个这样定义的主键:

PRIMARY KEY ((shop_id), dt_first_purchase, shopper_id)

基本上,哪个商店 (shop_id) 记录了特定购物者 (shopper_id) 的首次购买 (dt_first_purchase) 的记录

使用按商店 (shop_id) 划分的数据,您可以查询新购物者的首次购买特定的 shop_id,如下所示:

aploetz@cqlsh:***> SELECT * 
FROM first_purchase_by_shopper_date 
WHERE shop_id=ce1089f6-c613-4d5b-a975-5dfd677b46f9 
AND dt_first_purchase >= '2014-01-01 00:00:00' 
AND dt_first_purchase < '2014-04-01 00:00:00';

 shop_id                              | dt_first_purchase        | shopper_id                           | value
--------------------------------------+--------------------------+--------------------------------------+-------
 ce1089f6-c613-4d5b-a975-5dfd677b46f9 | 2014-02-12 18:33:22-0600 | a7480417-aaf8-42b1-85dd-5d9a4a30c204 | shopper1
 ce1089f6-c613-4d5b-a975-5dfd677b46f9 | 2014-03-13 11:33:22-0500 | 07db2b71-2dc7-421d-bf73-82a5f6c55f89 | shopper2

(2 rows)

此外,您还可以计算特定商店和日期范围内的首次购买(新购物者)数量,如下所示:

aploetz@cqlsh:***> SELECT COUNT(*) FROM first_purchase_by_shopper_date
WHERE shop_id=ce1089f6-c613-4d5b-a975-5dfd677b46f9 
AND dt_first_purchase >= '2014-01-01 00:00:00' 
AND dt_first_purchase < '2014-04-01 00:00:00';

 count
-------
     2

(1 rows)

请注意,此特定示例可能不适用于您的用例。了解它的本质:演示如何在 Cassandra 中进行分区和查询。

有关更多信息,请查看 Patrick McFadin 在Getting Started With Time Series Data Modeling 上的文章。他讨论了解决与您类似的用例的方法。

【讨论】:

很好的答案,感谢您抽出时间来举例说明。

以上是关于Cassandra 使用二级索引按日期过滤的主要内容,如果未能解决你的问题,请参考以下文章

二级索引的Cassandra查询:ReadTimeout:code = 1200

转换多索引数据框并按位置更改二级索引

DCE Cassandra 3.9 在加入现有集群期间创建二级索引缓慢

如何在无服务器框架中使用全局二级索引定义 DynamoDB 表

Cassandra索引详解

hbase coprocessor 二级索引