Проблема
У меня есть большой (> 500e6 строк) набор данных, который я поместил в базу данных pytables.
Допустим, первый столбец - это идентификатор, второй - счетчик для каждого идентификатора. каждая комбинация ID-счетчика должна быть уникальной. У меня есть одна неуникальная строка среди строк 500e6, которые я пытаюсь найти.
Для начала я сделал что-то вроде этого:
index1 = db.cols.id.create_index()
index2 = db.cols.counts.create_index()
for row in db:
query = '(id == %d) & (counts == %d)' % (row['id'], row['counts'])
result = th.readWhere(query)
if len(result) > 1:
print row
Я признаю, что это метод грубой силы. Есть предложения по улучшению?
обновить
текущее время работы методом перебора составляет 8421 минуту.
решение Всем спасибо за вклад. Мне удалось сократить время выполнения до 2364,7 секунды, используя следующий метод:
ex = tb.Expr('(x * 65536) + y', uservars = {"x":th.cols.id, "y":th.cols.counts})
ex = tb.Expr(expr)
ex.setOutput(th.cols.hash)
ex.eval()
indexrows = th.cols.hash.create_csindex(filters=filters)
ref = None
dups = []
for row in th.itersorted(sortby=th.cols.hash):
if row['hash'] == ref:
dups.append(row['hash'] )
ref = row['hash']
print("ids: ", np.right_shift(np.array(dups, dtype=np.int64), 16))
print("counts: ", np.array(dups, dtype=np.int64) & 65536-1)
Я могу сгенерировать идеальный хеш, потому что мои максимальные значения меньше 2 ^ 16. Я эффективно упаковываю два столбца в 32-битное int.
После того, как csindex сгенерирован, довольно просто перебрать отсортированные значения и выполнить проверку соседей на наличие дубликатов.
Этот метод, вероятно, можно немного изменить, но я тестирую несколько альтернатив, которые могут обеспечить более естественное решение.
threading.Thread
(или что-нибудь в этом роде), и просто живите с тем фактом, что наличие 1 плохой строки среди 500e6 (я выделил это жирным шрифтом, потому что это число просто смешно), другие - это игла в стоге сена? - person Aleksander Lidtke   schedule 23.12.2013th.readWhere('(id == cid) & (counts == ccounts)', {'cid': row['id'], 'ccounts': row['counts']})
. Если я правильно прочитал документы, это могло бы работать и быть быстрее. - person zch   schedule 23.12.2013where()
примерно в 3 раза быстрее (11,6 с), чем с использованиемreadWhere()
(35 с). Повторяю тесты с 1e6 строками. - person scrooge   schedule 28.12.2013