【问题标题】:How to select first record prior/after a given timestamp in KDB?如何在 KDB 中选择给定时间戳之前/之后的第一条记录?
【发布时间】:2014-04-14 08:35:03
【问题描述】:

我目前只是在时间戳前 1 分钟提取所有记录(例如,如果我感兴趣的时间戳是 2014.04.14T09:30):

select from Prices where timestamp within 2014.04.14T09:29 2014.04.14T09:30, stock=`GOOG

但是,这显然不是很健壮。有时之前的记录可能在09:25am,然后查询什么也不返回。有时,如果价格发生很大变化,查询可能会返回数百条记录,即使我只需要返回最后一条记录。

我知道这可以通过 asof 连接来完成,但暂时想避免它,因为 Prices 目前太大了。

我也有兴趣做同样的事情,但要找到给定时间戳之后的第一条记录。

还要注意Prices 是一个展开的表格

【问题讨论】:

    标签: database kdb q-lang


    【解决方案1】:

    选择给定时间戳之前的最后一条记录:

    q)select from Price where stock=`GOOG,i=last i,timestamp<2014.04.14T09:30
    

    选择给定时间戳之后的第一条记录:

    q)select from Price where stock=`GOOG,i=first i,timestamp>2014.04.14T09:30
    

    【讨论】:

    • 谢谢,但是如果Prices 被张开怎么办? aj 可以直接在张开的桌子上工作吗?我没想到,所以在使用aj 之前,我花了大量时间将Prices 的一部分读入内存。这就是我避免使用aj 的理由。
    【解决方案2】:

    使用asofaj 来获得kdb+ 所熟知的性能。价格越高,这样做的理由就越多。

    我会质疑你避免aj 的逻辑。 ajasof 使用 bin 运算符,它是二进制搜索,因此比扫描时间戳列更高效。

    让我们创建您的表并从另一个答案运行解决方案:

    Prices:([]stock:`g#1000000?`GOOG,9?`4;timestamp:asc 2014.04.14+1000000?0t;price:1000000?100f,size:1000000?100j)
    q)\t do[1000;select from Prices where timestamp<2014.04.14T09:30,stock=`GOOG,i=last i]
    10205
    

    我们可以通过重新排序约束来改善这一点:

    q)\t do[1000;select from Prices where stock=`GOOG,timestamp<2014.04.14T09:30,i=last i]
    2030
    

    但没有什么能比得上这个:

    q)\t do[1000;Prices asof `stock`timestamp!(`GOOG;2014.04.14D09:30)]
    9
    

    顺便说一句,您在您的问题中使用了 datetime,它已被弃用,因此我已将其替换为时间戳。这对性能没有影响。

    【讨论】:

      【解决方案3】:

      在使用aj 时要记住的更多事项:

      • 内存价格 - 表应该是`g#symtimesym 内排序
      • 磁盘价格 - `p#symtimesym 内排序

      同样在分区/展开表的情况下,使用where 约束(日期分区表中的date 除外)会严重影响性能。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-02-02
        • 2017-02-16
        • 2015-01-15
        • 1970-01-01
        • 2017-07-14
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多