首页 > 解决方案 > Pytables 复制 2.5 giga 行

问题描述

我目前有一个 .h5 文件,其中的表格由三列组成:一个 64 个字符的文本列,一个与文本源相关的 UInt32 列和一个 UInt32 列,它是文本的 xxhash。该表由 ~ 2.5e9 行组成

我正在尝试查找并计算表中每个文本条目的重复项 - 基本上将它们合并到一个条目中,同时计算实例。我已经尝试通过在哈希列上建立索引然后循环执行此操作table.itersorted(hash),同时跟踪哈希值并检查冲突 - 非常类似于在具有 500e6 行的 hdf5 pytable 中查找重复项。我没有在循环时修改表格,而是将合并的条目写入新表格 - 我将代码放在底部。

基本上我遇到的问题是整个过程花费的时间太长了——我花了大约 20 个小时才到达迭代 #5 4e5。但是,我正在使用硬盘驱动器,因此完全有可能存在瓶颈。你有什么方法可以改进我的代码,或者你能建议另一种方法吗?预先感谢您的任何帮助。

PS我保证我没有做任何违法的事情,这只是我的学士论文的大规模泄露密码分析。

ref = 3 #manually checked first occuring hash, to simplify the below code
gen_cnt = 0
locs = {}


print("STARTING")
for row in table.itersorted('xhashx'):
    gen_cnt += 1 #so as not to flush after every iteration
    ps = row['password'].decode(encoding = 'utf-8', errors = 'ignore')

    if row['xhashx'] == ref:
        if ps in locs:
            locs[ps][0] += 1
            locs[ps][1] |= row['src']

        else:
            locs[ps] = [1, row['src']]


    else:
        for p in locs:
            fill_password(new_password, locs[ps]) #simply fills in the columns, with some fairly cheap statistics procedures
            new_password.append()   

        if (gen_cnt > 100):
            gen_cnt = 0
            new_table.flush()  

        ref = row['xhashx']```


标签: pythonduplicateshdf5pytables

解决方案


您的数据集比引用的解决方案大 10 倍(2.5e9 与 500e6 行)。你有没有做过任何测试来确定时间花在哪里?该table.itersorted()方法可能不是线性的 - 并且可能是资源密集型的。(我没有任何迭代的经验。)

这是一个可能更快的过程:

  1. 提取哈希字段的 NumPy 数组(列xhashx
  2. 找到唯一的哈希值
  3. 遍历唯一的哈希值并提取与每个值匹配的 NumPy 行数组
  4. 对此提取的数组中的行进行唯一性测试
  5. 将唯一行写入新文件

下面这个过程的代码:
注意:这没有经过测试,所以可能有小的语法或逻辑差距

# Step 1: Get a Numpy array of the 'xhashx' field/colmu only:
hash_arr = table.read(field='xhashx')
# Step 2: Get new array with unique values only:
hash_arr_u = np.unique(hash_arr)

# Alternately, combine first 2 steps in a single step
hash_arr_u = np.unique(table.read(field='xhashx'))

# Step 3a: Loop on rows unique hash values
for hash_test in hash_arr_u :

# Step 3b: Get an array with all rows that match this unique hash value
     match_row_arr = table.read_where('xhashx==hash_test')

# Step 4: Check for rows with unique values
# Check the hash row count. 
# If there is only 1 row, uniqueness tested not required  
     if match_row_arr.shape[0] == 1 :
     # only one row, so write it to new.table

     else :
     # check for unique rows
     # then write unique rows to new.table

##################################################
# np.unique has an option to save the hash counts
# these can be used as a test in the loop
(hash_arr_u, hash_cnts) = np.unique(table.read(field='xhashx'), return_counts=True)

# Loop on rows in the array of unique hash values
for cnt in range(hash_arr_u.shape[0]) :

# Get an array with all rows that match this unique hash value
     match_row_arr = table.read_where('xhashx==hash_arr_u(cnt)')

# Check the hash row count. 
# If there is only 1 row, uniqueness tested not required  
     if hash_cnts[cnt] == 1 :
     # only one row, so write it to new.table

     else :
     # check for unique rows
     # then write unique rows to new.table

推荐阅读