hvt*_*org 4 cassandra cassandra-2.1
我使用的是 Cassandra 2.1,模型大致如下:
CREATE TABLE events (
client_id bigint,
bucket int,
timestamp timeuuid,
...
ticket_id bigint,
PRIMARY KEY ((client_id, bucket), timestamp)
);
CREATE INDEX events_ticket ON events(ticket_id);
Run Code Online (Sandbox Code Playgroud)
如您所见,我在 上创建了二级索引ticket_id。这个索引工作正常。events包含大约 1 亿行,而其中只有 500 万行有大约 50,000 个不同的票证。因此,一张门票平均包含 100 个事件。
查询二级索引无需提供分区键,这在我们的情况下很方便。由于该bucket列有时很难事先确定(即您应该知道事件的日期,bucket即当前日期)。
cqlsh> select * from events where ticket_id = 123;
client_id | bucket | timestamp | ... | ticket_id
-----------+--------+-----------+-----+-----------
(0 rows)
Run Code Online (Sandbox Code Playgroud)
当一张工单的所有事件都需要转移到另一张工单时,如何解决问题?即以下查询将不起作用:
cqlsh> UPDATE events SET ticket_id = 321 WHERE ticket_id = 123;
InvalidRequest: code=2200 [Invalid query] message="Non PRIMARY KEY ticket_id found in where clause"
Run Code Online (Sandbox Code Playgroud)
这是否意味着二级索引不能用于UPDATE?
我应该使用什么模型来支持这些变化?
首先, Cassandra 中的操作处理UPDATE方式INSERT是相同的。它们通俗地称为“UPSERT”。
这是否意味着二级索引不能在 UPDATE 查询中使用?
正确的。如果不指定完整的 PRIMARY KEY,则无法在 Cassandra 中执行 UPSERT。即使具有部分主键的 UPSERT 也不起作用。而且(正如您所发现的)按索引值进行 UPSERT 也不起作用。
当一张工单的所有事件都需要转移到另一张工单时,如何解决问题?
不幸的是,实现此目的的唯一方法是查询events(使用特定的ticket_id)中每一行的键,并ticket_id通过这些键进行 UPSERT。好处是,您不必首先使用DELETE它们,因为ticket_id它不是主键的一部分。
当一张工单的所有事件都需要转移到另一张工单时,如何解决问题?
我认为你最好的计划是放弃二级索引,并创建一个查询表来与你的events表一起工作:
CREATE TABLE eventsbyticketid (
client_id bigint,
bucket int,
timestamp timeuuid,
...
ticket_id bigint,
PRIMARY KEY ((ticket_id), timestamp)
) WITH CLUSTERING ORDER BY (timestamp DESC);
Run Code Online (Sandbox Code Playgroud)
这将允许您快速查询ticket_id(以获取您的client_id、bucket和)。这将为您提供在表上timestamp更新新内容所需的信息。ticket_idevents
然后您还可以执行DELETEby ticket_id(在eventsbyticketid桌子上)。DELETE只要您拥有完整的分区键 ( ),Cassandra 就允许使用部分主键进行操作ticket_id。ticket_id因此,从查询表中删除旧的s 会很容易。为了确保写入原子性,您可以将 UPSERT 一起批处理:
BEGIN BATCH
UPDATE events SET ticket_id = 321 WHERE client_id=2112 AND bucket='2015-04-22 14:53' AND timestamp=4a7e2730-e929-11e4-88c8-21b264d4c94d;
UPDATE eventsbyticketid SET client_id=2112, bucket='2015-04-22 14:53' WHERE ticket_id=321 AND timestamp=4a7e2730-e929-11e4-88c8-21b264d4c94d
APPLY BATCH;
Run Code Online (Sandbox Code Playgroud)
这实际上与执行相同:
BEGIN BATCH
INSERT INTO events (client_id,bucket,timestamp,ticketid) VALUES(2112,'2015-04-22 14:53',4a7e2730-e929-11e4-88c8-21b264d4c94d,321);
INSERT INTO eventsbyticketid (client_id,bucket,timestamp,ticketid) VALUES(2112,'2015-04-22 14:53',4a7e2730-e929-11e4-88c8-21b264d4c94d,321);
APPLY BATCH;
Run Code Online (Sandbox Code Playgroud)
旁注:timestamp实际上是 Cassandra 中的一种(保留字)数据类型。这使得它成为一个非常糟糕的timeuuid专栏名称。
| 归档时间: |
|
| 查看次数: |
2281 次 |
| 最近记录: |