如何使用python Dedupe有效地将记录链接到大表?

时间:2015-07-15 18:09:18

标签: python mysql record-linkage python-dedupe

我正在尝试使用Dedupe包将一个小杂乱的数据合并到规范表中。由于规范表非常大(1.22亿行),我无法将其全部加载到内存中。

我正在使用this的当前方法需要一整天的测试数据:存储在dict中的300k行杂乱数据表,以及存储在mysql中的600k行规范数据表。如果我在内存中完成所有操作(以dict的形式阅读规范表),它只需要半个小时。

有没有办法提高效率?

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)

2 个答案:

答案 0 :(得分:3)

通过将查询拆分为两个查询来大大加快速度。我正在使用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)

答案 1 :(得分:0)

如果您将查询表示为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"原始尝试中的语法很少被优化,也没有正确的连接。