0

问题:我们想从我们的数据库中删除拼写错误的地址。但是我们有太多的事情要做。因此,我有一个函数 FN,如果两个地址看起来非常相似(表明可能拼写错误),它会返回 true。一个简单的检查将是做类似的事情......

select *
from
    address adr1
    join address adr2
    on FN(adr1, adr2)

但是,这基本上是进行交叉连接并比较行。由于我们的表有多大(> 100 万行),这是不可能做到的。但是,我可以将其限制为仅查看彼此附近的地址。例如,同一城市内的地址。所以,我试着做这样的地址计数......

select count(1)
from
    address adr1
    join address adr2
    on adr1.zip = adr2.zip
    and adr1.city = adr2.city
    --Don't want to compare to self
    and adr1.ID <> adr2.ID

问题是这需要很长时间才能运行(我已经等了但它仍然没有完成)。我怀疑 oracle 有更好的方法来处理大量行的这些类型的事情,但我只是不知道。

那么,如果有办法限制正在加入的内容(例如只在同一个邮政编码中查找),那么一个人应该如何将一个极大的表加入到自己身上呢?

PS 数以万亿计的记录算作大数据还是应该删除标签?

Edit1: Zip 和 City 已编入索引。

Edit2:Zip 和 City 都有大量的空值 200,000+。这可能会影响索引在连接中的使用方式。

解释计划:

SELECT STATEMENT  ALL_ROWSCost: 35,301  Bytes: 42  Cardinality: 1           
    4 SORT AGGREGATE  Bytes: 42  Cardinality: 1         
        3 HASH JOIN  Cost: 35,301  Bytes: 2,195,769,492  Cardinality: 52,280,226    
            1 TABLE ACCESS FULL TABLE SCHEMA.ADDRESS Cost: 15,677  Bytes: 21,388,962  Cardinality: 1,018,522  
            2 TABLE ACCESS FULL TABLE SCHEMA.ADDRESS Cost: 15,677  Bytes: 21,388,962  Cardinality: 1,018,522  

Edit3:我试过计算我将以不同方式查看的行数。

select
    sum(cnt * (cnt - 1))
from
(
select
    count(1) as CNT
from schema.address adr1
group by adr1.zip, adr1.city
)

这在不到 10 秒的时间内返回了约 450 亿个不同的配对。我不确定我的函数每秒可以处理超过 100k 行,这是在 12 小时内运行所需要的。

4

3 回答 3

1

1)在字段上建立索引ZIPCITY

2)要获得重复项(这是您在第二种情况下所做的),请使用GROUP BY

SELECT ZIP,CITY, count(*) FROM ADDRESS HAVING COUNT(*)>1 GROUP BY ZIP,CITY
于 2013-06-06T20:08:44.200 回答
1

我有一些好消息,也有一些坏消息。

好消息是您现有的查询可能有接近 50 亿行,而不是 450 亿行。

坏消息是,这是因为它不会尝试匹配 200,000 条具有 null zip 或 null city 值的记录中的任何一条——Oracle(以及我知道的所有其他 RDBMS)不会将 NULL 值连接到其他 NULL 值;看这里的例子。您可以使用 acoalesce作为连接条件的一部分来解决这个问题,但我建议单独处理空城市/zip 记录。

假设您的函数对称地处理地址(以便FN(addr1,addr2)返回与 相同的结果),您可以通过在现有查询中更改为FN(addr2,addr1)来进一步将组合数量减半。如果您还没有合适的索引,我建议在 zip、city 和 id 上添加一个(按此顺序)。adr1.ID <> adr2.IDadr1.ID < adr2.ID

于 2013-06-07T15:11:55.243 回答
0

如果相关地址/国家/地区存在邮政授权 idcode,则另一种方法是使用邮政管理局 idcode 对每个地址进行编码。这意味着您无需将每个地址与其自身进行比较,而是首先将所有精力放在解析和解码地址上。我们使用这种方法,并将 id 存储在每一行中,这意味着我们以后可以非常精确和快速地加入。

如果您不能使用邮政 ID(我的意思是邮局分配的每个送货地址的唯一 ID),请考虑对每个地址进行地理编码,然后通过地理附近的地址加入。如果地址不是纯粹的邮政地址,地理编码也可能适用。

我也对 FN() 对地址的作用很感兴趣,你看到http://www.mjt.me.uk/posts/falsehoods-programmers-believe-about-addresses/与你的问题无关,但是如果您不熟悉地址处理,请好好阅读。

于 2013-06-08T07:40:33.207 回答