【问题标题】:How do I insert data to a disk table quickly on KDB?如何在 KDB 上快速将数据插入磁盘表?
【发布时间】:2021-07-25 16:24:19
【问题描述】:

我有大约 10,000 个符号的 5 年分钟柱,作为 CSV 文件。它总共有大约 50GB 的文本。我的内存是 32GB。

我正在尝试将所有这些数据加载到 KDB 表中,以便轻松查询。

symbols: `$(-4_')(string') key `:/home/chris/sync/us_equities

f: {`$(":/home/chris/sync/us_equities/", x, ".csv")}

load_symbol: {(0!(update "P"$-1_/:t, s: x from flip `t`o`h`l`c`v!("*FFFFI";",")0: f(string x))) }

({`:/home/chris/sync/price_data insert (load_symbol x)}) each symbols
  • 我应该使用简单的表,还是应该使用分区/splays?
  • 我将代码添加为符号类型的额外列;对吗?
  • 最后一行insert 非常缓慢。看起来需要大约一天的时间来处理,也许更长。我该如何优化它?我试过peach,但这更慢。看起来它开始非常快,并且随着each 的每一步而变慢。

谢谢!

【问题讨论】:

    标签: kdb


    【解决方案1】:

    由于数据大小和更新频率的原因,不建议在这种情况下使用平面文件。每次插入时都需要从头开始重新创建文件,导致插入时间与总行数成线性关系。

    q)t:([]a:til 10000000;b:til 10000000)
    q)`:t set t
    `:t
    q)\t `:t insert t
    305
    q)\t `:t insert t
    365
    q)\t `:t insert t
    574
    q)\t `:t insert t
    809
    q)\t `:t insert t
    1236
    q)\t `:t insert t
    2687
    q)\t `:t insert t
    3200
    

    将此与展开表进行比较,其中新数据中的每一列都附加到相应的文件中,从而导致不断插入。

    q)t:([]a:til 10000000;b:til 10000000)
    q)`:t/ set t
    `:t/
    q)\t `:t insert t
    166
    q)\t `:t insert t
    101
    q)\t `:t insert t
    97
    q)\t `:t insert t
    100
    q)\t `:t insert t
    111
    q)\t `:t insert t
    113
    

    如果符号不在文件中,那么将其添加到表中是明智的。不过,我建议将列命名为 sym 而不是 s。这只是因为它在 kdb 中是常规的,并且一些内置函数采用了这个名称。

    据我估计,这张桌子对于一张简单的张开桌子来说太大了。我会按日期或月份对其进行分区,具体取决于您正在运行的查询类型。

    如果您的查询经常选择符号的子集,则必须按符号排序并添加parted attribute。需要使用asof join,因为它使用二进制搜索。

    以下代码将执行此操作,但由于您的文件已经由 sym 分隔,您应该可以跳过 sym 排序。

    / to sort a table in memory and apply parted attribute
    update `p#sym from `sym`time xasc data 
    / to sort a table on disk and apply parted attribute
    sym`time xasc `:path/to/partition
    @[`:path/to/partition;`sym;`p#]
    

    如果您的查询更适合在所有符号中选择特定时间窗口,您最好只按时间段排序并将排序属性应用于此列。

    此外,您可能需要考虑使用 .Q.fs.Q.fsn 流式传输 csv 文件,以减少任何单个加载的内存使用量。这将允许您使用多线程或其他进程以相同的内存开销加载数据。

    【讨论】:

    • 我已按照您的建议进行操作,包括确保数据已对 t 进行了排序,并将 sym 标志与 upsert 分开。但是,我发现一个简单的查询select from disk where sym = ```AAPL 大约需要 5.5 秒,比读取 CSV 慢 8 倍。我不确定会发生什么。查看文件夹,每列都有文件,但没有额外的文件夹(所以我不确定它是否正确分开)。
    • 补充一下,最终文件包含160m行。
    • 您只需要在对分区完成翻转后应用一次parted属性`p。您可以通过attr get `:path/to/partition/sym 来检查这是否已正确应用。顺便说一句,你是如何计时的?如果使用客户端,则包括通过网络传输数据的时间
    • 哇,快了 4000 倍!它现在比使用 CSV 快得多。 ````p` 是否只是在sym 上创建了一个索引,还是数据正在磁盘上重新排列?我正在用\t 测量时间;它都在我的本地主机上运行。顺便感谢您的帮助!
    • 我补充一下,我无法运行 sym`time xasc `:path/to/partition - 这导致 KDB 内存不足。
    猜你喜欢
    • 2014-05-02
    • 1970-01-01
    • 2012-03-04
    • 2010-10-04
    • 2012-06-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多