我如何使用 python Dedupe 有效地将 link 记录到大型 table?
How do I link records to a large table efficiently using python Dedupe?
我正在尝试使用 Dedupe
程序包将一些杂乱的数据合并为规范的 table。由于规范 table 非常大(1.22 亿行),我无法将其全部加载到内存中。
我目前使用的方法基于 this 需要一整天的时间来处理测试数据:30 万行 table 存储在字典中的杂乱数据,以及 60 万行 table 的规范数据存储在 mysql 中。如果我在内存中完成所有操作(阅读规范的 table 作为字典)只需要半小时。
有没有办法提高效率?
blocked_pairs = block_data(messy_data, canonical_db_cursor, gazetteer)
clustered_dupes = gazetteer.matchBlocks(blocked_pairs, 0)
def block_data(messy_data, c, gazetteer):
block_groups = itertools.groupby(gazetteer.blocker(messy_data.viewitems()),
lambda x: x[1])
for (record_id, block_keys) in block_groups:
a = [(record_id, messy_data[record_id], set())]
c.execute("""SELECT *
FROM canonical_table
WHERE record_id IN
(SELECT DISTINCT record_id
FROM blocking_map
WHERE block_key IN %s)""",
(tuple(block_key for block_key, _ in block_keys),))
b = [(row[self.key], row, set()) for row in c]
if b:
yield (a, b)
通过将查询拆分为两个查询来显着加快速度。我正在使用 mysql
并且示例中使用的所有列都已编入索引...
def block_data(messy_data, c, gazetteer):
block_groups = itertools.groupby(gazetteer.blocker(messy_data.viewitems()),
lambda x: x[1])
for (record_id, block_keys) in block_groups:
a = [(record_id, messy_data[record_id], set())]
c.execute("""SELECT DISTINCT record_id
FROM blocking_map
WHERE block_key IN %s""",
(tuple(block_key for block_key, _ in block_keys),))
values = tuple(row['record_id'] for row in c)
if values:
c.execute("""SELECT *
FROM canonical_table
WHERE record_id IN %s""",
(values,))
b = [(row['record_id'], row, set())
for row in c]
if b:
yield (a, b)
如果您将查询表示为 JOIN,可能会更快:
SELECT canonical_table.*
FROM canonical_table
JOIN blocking_map
ON (canonical_table.record_id = blocking_map.record_id)
WHERE blocking_map IN %s
您的解决方案基本上是在 Python 中进行连接,因此数据库可能会做得更好。您最初尝试的 "IN" 语法很少像正确的连接一样得到优化。
我正在尝试使用 Dedupe
程序包将一些杂乱的数据合并为规范的 table。由于规范 table 非常大(1.22 亿行),我无法将其全部加载到内存中。
我目前使用的方法基于 this 需要一整天的时间来处理测试数据:30 万行 table 存储在字典中的杂乱数据,以及 60 万行 table 的规范数据存储在 mysql 中。如果我在内存中完成所有操作(阅读规范的 table 作为字典)只需要半小时。
有没有办法提高效率?
blocked_pairs = block_data(messy_data, canonical_db_cursor, gazetteer)
clustered_dupes = gazetteer.matchBlocks(blocked_pairs, 0)
def block_data(messy_data, c, gazetteer):
block_groups = itertools.groupby(gazetteer.blocker(messy_data.viewitems()),
lambda x: x[1])
for (record_id, block_keys) in block_groups:
a = [(record_id, messy_data[record_id], set())]
c.execute("""SELECT *
FROM canonical_table
WHERE record_id IN
(SELECT DISTINCT record_id
FROM blocking_map
WHERE block_key IN %s)""",
(tuple(block_key for block_key, _ in block_keys),))
b = [(row[self.key], row, set()) for row in c]
if b:
yield (a, b)
通过将查询拆分为两个查询来显着加快速度。我正在使用 mysql
并且示例中使用的所有列都已编入索引...
def block_data(messy_data, c, gazetteer):
block_groups = itertools.groupby(gazetteer.blocker(messy_data.viewitems()),
lambda x: x[1])
for (record_id, block_keys) in block_groups:
a = [(record_id, messy_data[record_id], set())]
c.execute("""SELECT DISTINCT record_id
FROM blocking_map
WHERE block_key IN %s""",
(tuple(block_key for block_key, _ in block_keys),))
values = tuple(row['record_id'] for row in c)
if values:
c.execute("""SELECT *
FROM canonical_table
WHERE record_id IN %s""",
(values,))
b = [(row['record_id'], row, set())
for row in c]
if b:
yield (a, b)
如果您将查询表示为 JOIN,可能会更快:
SELECT canonical_table.*
FROM canonical_table
JOIN blocking_map
ON (canonical_table.record_id = blocking_map.record_id)
WHERE blocking_map IN %s
您的解决方案基本上是在 Python 中进行连接,因此数据库可能会做得更好。您最初尝试的 "IN" 语法很少像正确的连接一样得到优化。