【问题标题】:How do I link records to a large table efficiently using python Dedupe?如何使用 python Dedupe 有效地将记录链接到大表?
【发布时间】:2015-07-15 18:09:18
【问题描述】:

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

我目前使用的基于this 的方法需要一整天的时间来处理测试数据:存储在 dict 中的 300k 行杂乱数据表,以及存储在 mysql 中的 600k 行规范数据表。如果我在内存中完成所有操作(将规范表作为字典读取)只需要半个小时。

有没有办法提高效率?

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)

【问题讨论】:

    标签: python mysql record-linkage python-dedupe


    【解决方案1】:

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

    【讨论】:

      【解决方案2】:

      如果您将查询表示为 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”语法很少得到优化以及正确的连接。

      【讨论】:

        猜你喜欢
        • 2022-06-24
        • 1970-01-01
        • 2011-05-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多