【问题标题】:Cassandra search by date from timestamp columnCassandra 从时间戳列按日期搜索
【发布时间】:2021-10-15 17:37:06
【问题描述】:

从 Cassandra 表中如何从时间戳列中获取基于日期的记录。表的详细信息是

   CREATE TABLE hlragent_logs.hlragent_logs_2021 (
    msisdn text,
    date_time timestamp,
    cmd_no text,
    agent_id text,
    cmd_executed text,
    dummy text,
    id bigint,
    imsi text,
    mml_cmd text,
    module text,
    node text,
    node_id text,
    node_ip text,
    p text,
    pno text,
    serial text,
    vhlr_name text,
    PRIMARY KEY (msisdn, date_time, cmd_no)
) WITH CLUSTERING ORDER BY (date_time ASC, cmd_no ASC)
    AND bloom_filter_fp_chance = 0.01
    AND caching = {'keys': 'ALL', 'rows_per_partition': 'NONE'}
    AND comment = ''
    AND compaction = {'class': 'org.apache.cassandra.db.compaction.SizeTieredCompactionStrategy', 'max_threshold': '32', 'min_threshold': '4'}
    AND compression = {'chunk_length_in_kb': '64', 'class': 'org.apache.cassandra.io.compress.LZ4Compressor'}
    AND crc_check_chance = 1.0
    AND dclocal_read_repair_chance = 0.1
    AND default_time_to_live = 0
    AND gc_grace_seconds = 864000
    AND max_index_interval = 2048
    AND memtable_flush_period_in_ms = 0
    AND min_index_interval = 128
    AND read_repair_chance = 0.0
    AND speculative_retry = '99PERCENTILE';
CREATE INDEX indx_agentlogs_2021 ON hlragent_logs.hlragent_logs_2021 (imsi)

select * from hlragent_logs_2021 where todate(date_time)="2021-08-10" 允许过滤; SyntaxException:第 1:45 行在输入 '(' 处没有可行的替代方案(select * from hlragent_logs_2021 where todate

【问题讨论】:

    标签: cassandra


    【解决方案1】:

    您不能在 WHERE 子句中使用用户定义的函数(有一个 Jira ticket for it,但我不记得有人在使用它)。

    【讨论】:

    • todate 是一个时间戳函数,用于操作 INSERT、UPDATE 和 SELECT 语句中使用的日期。 select * from hlragent_logs_2021 where date_time>='2021-08-10' and mml_cmd='DEL USER' 允许过滤 this is woking
    • 我知道todate 是什么——你根本不能在 where 条件下使用它。您可以查看 CQL 语法以查看不支持的函数:github.com/apache/cassandra/blob/trunk/src/antlr/Parser.g#L1672
    【解决方案2】:

    不必使用本机 CQL TODATE() 函数来处理时间戳列。可以通过以下方式直接处理列:

    SELECT * FROM ... WHERE ... AND date_time < "2021-08-10";
    

    但是您不能使用相等运算符 (=),因为 CQL 时间戳数据类型是 encoded as the number of milliseconds since Unix epoch(格林威治标准时间 1970 年 1 月 1 日 00:00),因此您在使用时间戳时需要精确。

    根据您运行查询的位置,过滤器可以在本地时区进行翻译。让我用这个示例表来说明:

    CREATE TABLE community.tstamptbl (
        id int,
        tstamp timestamp,
        PRIMARY KEY (id, tstamp)
    )
    

    这 2 个语句可能看起来相似,但翻译成 2 个不同的条目:

    INSERT INTO tstamptbl (id, tstamp) VALUES (5, '2021-08-09');
    
    INSERT INTO tstamptbl (id, tstamp) VALUES (5, '2021-08-09 +0000');
    

    第一个语句创建一个带有我当地时区(澳大利亚墨尔本)时间戳的条目,而第二个语句创建一个带有 UTC 时间戳的条目(+0000):

    cqlsh:community> SELECT * FROM tstamptbl WHERE id = 5;
    
     id | tstamp
    ----+---------------------------------
      5 | 2021-08-08 14:00:00.000000+0000
      5 | 2021-08-09 00:00:00.000000+0000
    

    同样,您在读取数据时也需要精确。您需要指定时区以消除歧义。以下是一些示例:

    SELECT * FROM tstamptbl WHERE id = 5 AND tstamp < '2021-08-09 +0000';
    SELECT * FROM tstamptbl WHERE id = 5 AND tstamp < '2021-08-10 12:00+0000';
    SELECT * FROM tstamptbl WHERE id = 5 AND tstamp < '2021-08-08 12:34:56+0000';
    

    同样,由于时间戳以毫秒(而不是天)为单位进行编码,因此给定日期的可能值范围很广。如果我想检索日期 2021-08-09 的所有行,我需要根据此示例中的范围进行过滤:

    SELECT * FROM tstamptbl 
    WHERE id = 5
        AND tstamp >= '2021-08-09 +0000'
        AND tstamp < '2021-08-10 +0000';
    

    干杯!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-05-08
      • 2018-08-28
      • 2022-01-24
      • 2013-07-11
      • 2016-05-21
      • 1970-01-01
      • 2019-03-01
      相关资源
      最近更新 更多