微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Levenshtein距离的模糊连接

如何解决Levenshtein距离的模糊连接

我有一个表,其中包含名为“ potential_users”的用户名(约1000行)和另一个名为“ actual_users”的表(约1000万行)。所有记录仅由[a-z]字符组成,没有空格。另外,我知道Actual_users表中都没有电位用户

我希望能够根据Levenshtein距离,为电位用户中的每一行计算出实际用户中最接近的记录。例如:

| potential_users|
|----------------|
| user1          |
| kajd           |
| bbbbb          |

| actual_users |
|--------------|
| kaj          |
| bbbbbbb      |
| user         |

会返回:

| potential_users | actual_users | levenshtein_distance |
|-----------------|--------------|----------------------|
| user1           | user         | 1                    |
| kajd            | kaj          | 1                    |
| bbbbb           | bbbbbbb      | 2                    |

如果表很短,我可以做一个交叉连接,该交叉连接将为potential_users中的每条记录计算实际_users中的Levenshtein距离,然后返回最小值。但是,在我的情况下,这将创建一个包含1000 x 10000000行的中间表,这有点不切实际。

是否存在创建交叉连接的更清洁方法

解决方法

不幸的是,没有交叉联接就无法做到这一点。最终,每个潜在用户都需要针对每个实际用户进行测试。

但是,Presto将在许多线程和机器上并行执行联接,因此只要有足够的硬件,它就可以非常快地执行。请注意,在Presto中,中间结果在运算符之间流传输,因此对于该查询,没有“中间表”具有10M x 1k行。

对于类似

的查询
SELECT potential,min_by(actual,distance),min(distance)
FROM (
    SELECT *,levenshtein_distance(potential,actual) distance
    FROM actual_users,potential_users
)
GROUP BY potential

这是查询计划:

                                                   Query Plan                                                   
----------------------------------------------------------------------------------------------------------------
 Fragment 0 [SINGLE]                                                                                            
     Output layout: [potential,min_by,min]                                                                    
     Output partitioning: SINGLE []                                                                             
     Stage Execution Strategy: UNGROUPED_EXECUTION                                                              
     Output[potential,_col1,_col2]                                                                            
     │   Layout: [potential:varchar(5),min_by:varchar(7),min:bigint]                                          
     │   Estimates: {rows: ? (?),cpu: ?,memory: ?,network: ?}                                                
     │   _col1 := min_by                                                                                        
     │   _col2 := min                                                                                           
     └─ RemoteSource[1]                                                                                         
            Layout: [potential:varchar(5),min:bigint]                                       
                                                                                                                
 Fragment 1 [HASH]                                                                                              
     Output layout: [potential,min]                                                                    
     Output partitioning: SINGLE []                                                                             
     Stage Execution Strategy: UNGROUPED_EXECUTION                                                              
     Aggregate(FINAL)[potential]                                                                                
     │   Layout: [potential:varchar(5),min:bigint,min_by:varchar(7)]                                          
     │   Estimates: {rows: ? (?),network: ?}                                                
     │   min := min("min_1")                                                                                    
     │   min_by := min_by("min_by_0")                                                                           
     └─ LocalExchange[HASH] ("potential")                                                                       
        │   Layout: [potential:varchar(5),min_1:bigint,min_by_0:row(boolean,boolean,bigint,varchar(7))]    
        │   Estimates: {rows: ? (?),network: ?}                                             
        └─ RemoteSource[2]                                                                                      
               Layout: [potential:varchar(5),varchar(7))] 
                                                                                                                
 Fragment 2 [SOURCE]                                                                                            
     Output layout: [potential,min_1,min_by_0]                                                                
     Output partitioning: HASH [potential]                                                                      
     Stage Execution Strategy: UNGROUPED_EXECUTION                                                              
     Aggregate(PARTIAL)[potential]                                                                              
     │   Layout: [potential:varchar(5),varchar(7))]       
     │   min_1 := min("levenshtein_distance")                                                                   
     │   min_by_0 := min_by("actual","levenshtein_distance")                                                   
     └─ Project[]                                                                                               
        │   Layout: [actual:varchar(7),potential:varchar(5),levenshtein_distance:bigint]                      
        │   Estimates: {rows: ? (?),network: ?}                                             
        │   levenshtein_distance := levenshtein_distance("potential","actual")                                 
        └─ CrossJoin                                                                                            
           │   Layout: [actual:varchar(7),potential:varchar(5)]                                                
           │   Estimates: {rows: ? (?),network: ?}                                          
           │   Distribution: REPLICATED                                                                         
           ├─ TableScan[memory:9,grouped = false]                                                              
           │      Layout: [actual:varchar(7)]                                                                   
           │      Estimates: {rows: ? (?),memory: 0B,network: 0B}                                     
           │      actual := 0                                                                                   
           └─ LocalExchange[SINGLE] ()                                                                          
              │   Layout: [potential:varchar(5)]                                                                
              │   Estimates: {rows: ? (?),network: ?}                                      
              └─ RemoteSource[3]                                                                                
                     Layout: [potential:varchar(5)]                                                             
                                                                                                                
 Fragment 3 [SOURCE]                                                                                            
     Output layout: [potential]                                                                                 
     Output partitioning: BROADCAST []                                                                          
     Stage Execution Strategy: UNGROUPED_EXECUTION                                                              
     TableScan[memory:8,grouped = false]                                                                       
         Layout: [potential:varchar(5)]                                                                         
         Estimates: {rows: ? (?),network: 0B}                                              
         potential := 0                                                                                         
                                                                                                                
                                                                                                                
(1 row)

尤其是对于此部分,只要通过交叉连接生成一行,就会将其馈入到投影运算符中,该运算符将计算两个值之间的Levenshtein距离,然后馈入聚合中,每个聚合中仅存储一组“潜在”用户。因此,此查询所需的内存量应该少。

     Aggregate(PARTIAL)[potential]                                                                              
     │   Layout: [potential:varchar(5),network: ?}                                          
           │   Distribution: REPLICATED 
,

我认为您不能通过简单的join来做到这一点,有整个算法可以计算出来。看这篇文章显示了Levenshtein距离算法在sql中的实现:

https://www.sqlteam.com/forums/topic.asp?TOPIC_ID=51540&whichpage=1

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。