10

你如何通过timeuuid查询和过滤,即假设你有一个表

create table mystuff(uuid timeuuid primary key, stuff text);

即你怎么做:

select uuid, unixTimestampOf(uuid), stuff
from mystuff
order by uuid desc
limit 2000

我还希望能够获取下一个较旧的 2000 等等,但这是一个不同的问题。错误是:

Bad Request: ORDER BY is only supported when the partition key is restricted by an EQ or an IN.

以防万一,真正的表格实际上是这样的:

CREATE TABLE audit_event (
  uuid timeuuid PRIMARY KEY,
  event_time bigint,
  ip text,
  level text,
  message text,
  person_uuid timeuuid
) WITH
  bloom_filter_fp_chance=0.010000 AND
  caching='KEYS_ONLY' AND
  comment='' AND
  dclocal_read_repair_chance=0.000000 AND
  gc_grace_seconds=864000 AND
  read_repair_chance=0.100000 AND
  replicate_on_write='true' AND
  populate_io_cache_on_flush='false' AND
  compaction={'class': 'SizeTieredCompactionStrategy'} AND
  compression={'sstable_compression': 'SnappyCompressor'};
4

1 回答 1

20

我建议你设计你的桌子有点不同。用你目前的设计来实现你所要求的将是相当困难的。

目前,您在audit_event表中的每个条目都会收到另一个uuid,Cassandra 在内部将创建许多短行。查询这样的行效率低下,而且它们是随机排序的(除非使用字节排序分区器,你应该避免这样做有充分的理由)。

然而,Cassandra 非常擅长对列进行排序。如果(回到你的例子)你声明你的表是这样的:

CREATE TABLE mystuff(
  yymmddhh varchar, 
  created timeuuid,  
  stuff text, 
  PRIMARY KEY(yymmddhh, created)
);

Cassandra 在内部会创建一行,其中键是一天中的小时,列名是实际创建的时间戳,数据是内容。这将使查询变得高效。

考虑你有以下数据(为了更容易,我不会去 2k 记录,但想法是一样的):

insert into mystuff(yymmddhh, created, stuff) VALUES ('13081615', now(), '90');
insert into mystuff(yymmddhh, created, stuff) VALUES ('13081615', now(), '91');
insert into mystuff(yymmddhh, created, stuff) VALUES ('13081615', now(), '92');
insert into mystuff(yymmddhh, created, stuff) VALUES ('13081615', now(), '93');
insert into mystuff(yymmddhh, created, stuff) VALUES ('13081615', now(), '94');
insert into mystuff(yymmddhh, created, stuff) VALUES ('13081616', now(), '95');
insert into mystuff(yymmddhh, created, stuff) VALUES ('13081616', now(), '96');
insert into mystuff(yymmddhh, created, stuff) VALUES ('13081616', now(), '97');
insert into mystuff(yymmddhh, created, stuff) VALUES ('13081616', now(), '98');

现在假设我们要选择最后两个条目(假设我们知道“最新”行键是“13081616”),您可以通过执行如下查询来完成:

SELECT * FROM mystuff WHERE yymmddhh = '13081616' ORDER BY created DESC LIMIT 2 ;

这应该给你这样的东西:

 yymmddhh | created                              | stuff
----------+--------------------------------------+-------
 13081616 | 547fe280-067e-11e3-8751-97db6b0653ce |    98
 13081616 | 547f4640-067e-11e3-8751-97db6b0653ce |    97

要获取接下来的 2 行,您必须从created列中获取最后一个值并将其用于下一个查询:

SELECT * FROM mystuff WHERE  yymmddhh = '13081616' 
AND created < 547f4640-067e-11e3-8751-97db6b0653ce 
ORDER BY created DESC LIMIT 2 ;

如果您收到的行数少于预期,则应将行键更改为另一个小时。

行键处理/计算

现在我假设我们知道我们想要查询数据的行键。如果您记录大量信息,我会说这不是问题 - 您可以只使用当前时间并发出查询,将小时设置为我们现在的时间。如果我们用完了行,我们可以减去一个小时并发出另一个查询。

但是,如果您不知道数据的位置,或者数据分布不均,则可以创建元数据表,在其中存储有关行键的信息:

CREATE TABLE mystuff_metadata(
  yyyy varchar, 
  yymmddhh varchar, 
  PRIMARY KEY(yyyy, yymmddhh)
) WITH COMPACT STORAGE;

行键将按年份组织,因此要获取当前年份的最新行键,您必须发出查询:

SELECT yymmddhh 
FROM  mystuff_metadata where yyyy = '2013' 
ORDER BY yymmddhh DESC LIMIT 1;

您的审计软件必须在开始时和稍后每小时更改时(例如在将数据插入到之前mystuff)对该表进行条目。

于 2013-08-16T15:27:42.590 回答