为 HDF5 中的列中的每个唯一值查找上次时间戳的有效方法 table

efficient way to find last time stamp for each unique value in a column in HDF5 table

如何有效地找到 SecurityID 列中每个唯一值的最后一个时间戳(从 Datetime 列)? SecurityID 列中大约有 1000 个唯一值。

目前我在整个 table 中查询 SecurityID 中的每个唯一值,然后查找最后一个时间戳。正如您可能想象的那样,它非常缓慢。 table 超过 40GB,并且还在增加。

我是这样做的:

os.chdir('E:\HDFStores')
store = pd.HDFStore('mysuperawesomehdfstore.h5')
assets = skBase.bbg_helper_assets('minutely')
df_timestamp = pd.Dataframe()
tags = ['T', 'B', 'A']
for asset in assets:
    for tag in tags:
        print asset, " ", tag
        timestamp = (store.select('table', where = "SecurityID = ['" + asset + "'] & Tag = ['" + tag + "'] & columns = ['Datetime']")).tail(1)
        if len(timestamp_.index) == 0:
            print "value DNE"
        else:
            dt = (str(timestamp_iloc[0][0])).split(' ', 1)[0]
            tm = (str(timestamp_iloc[0][0])).split(' ', 1)[1]

我考虑过在我的 4 核机器中 运行 单独的 python 进程。但我宁愿有一种更简洁的做事方式,也不愿求助于那种 hack。

如有任何想法,我们将不胜感激。

因为你的数据库很大,需要从硬盘查询,IO瓶颈

这实际上是这里的主要问题。智能代码无法真正弥补必须查询 40gb 文件的问题——尤其是考虑到您的查询非常简单。多处理也无济于事(这不是 CPU 瓶颈)。所以我认为解决方案是通过更新您的工作流程来实现的。

所有解决方案都依赖于异步操作(首先处理所有数据,将其转储到单独的文件,根据需要从该文件中读取),或者重新组织存储数据的方式。

异步 1

如果您更新主 HDF5 文件的频率低于每天,您可以简单地:

更新主 HDF5 后,查询所有 securityID 的最新时间戳(使用您现有的代码)。将结果转储到一个单独的 H5 文件中(只是索引:SecurityID,值:最新时间戳)。当然,这个解决方案只有在每个查询不到 30 秒的情况下才有效(那已经需要将近半天了...)

然后您可以将此数据保存在内存中(应该只有几 Kb),并在需要了解特定 SecurityID 的最新时间戳时随时访问它。

异步 2

更聪明的方法(但工作量更大)是在收到更新数据时读取最后一个时间戳。我不知道你是如何更新你的 HDF5 文件的,但我猜你正在下载新数据,并将其附加到当前文件中。

在那种情况下,这将是获取最新时间戳数据的最佳时机。您的工作流程将变为:

  1. 下载新数据
  2. 从新数据中,为每个 SecurityID 获取最新的时间戳
  3. 转储/更新您的 'latest_timestamp' h5 文件
  4. 用新数据更新您的主 HDF5

H5重组

如果上述解决方案的 none 看起来可行,那么您可以将每个 SecurityID 作为单独的节点存储在 h5 文件中。所以你会做类似的事情:

store.select(asset, where = Tag = ['" + tag + "'] & columns ['Datetime']")).tail(1)

调整其余代码(以及重新组织数据库的前期工作)可能需要做更多的工作,但这应该会大大减少查询时间,而且从长远来看会有帮助。我看不出有什么好的理由将所有 SecurityID 集中在一个巨大的节点中。而且它比其他解决方案更简单:-)