Mysql LEFT JOIN 在两个参数上进行,在非常大的表上有一个精确匹配和一个 LIKE 匹配 - 性能

标签 mysql

我有两个历史数据表 - 一个 (OldData) 是来自数据源的 40,000 条记录,其中包含我试图清理的部分/不准确数据,另一个 (LookupData) 是超过 100 万条准确记录的明确来源。

我正在尝试使用较大表中的记录来丰富第一个较小的表,并且我可以通过连接姓氏和称为服务编号的数值来预测匹配记录,但在第一个表中,这些数字通常不完整.

OldData(部分/不准确的数据)示例:

Surname | ServiceNumber
Smith | 12345
Jones | 9876
Brown | 234

LookupData 示例:

Surname | ServiceNumber
SMITH | 12345
SMITH | 23456
JONES | 98765 
JONES | 19182
BROWN | T12345 
BROWN | 56789

期望的结果:

OldData.Surname | OldData.ServiceNumber | LookupData.ServiceNumber
Smith | 12345 | 12345
Jones | 9876  | 98765
Brown | 234   | T12345

我当前的查询是

SELECT OldData.*,LookupData.ServiceNumber
FROM `OldData` 
LEFT JOIN `LookupData` 
ON lower(OldData.Surname) = lower(LookupData.Surname) 
AND LookupData.ServiceNumber like concat('%',OldData.ServiceNumber,'%') 

但这似乎永远不会完成

如果我将其缩小到一个姓氏进行测试,并添加

WHERE OldData.Surname='Devlin'

我从 OldData 中获取了 47 行,并在找到任何匹配项时获取了准确的 LookupData.ServiceNumber(在未找到匹配项时获取 null),但此查询平均仍需要 27 秒。

我在“姓氏”字段和“ServiceNumber”字段上都有索引。

如果我正在寻找不可能的事情,我至少想知道:)谢谢

最佳答案

让我们看看查询的两个 JOIN 条件。

lower(OldData.Surname) = lower(LookupData.Surname) 

在等式的两端使用函数会减慢搜索速度。默认情况下,MySQL 字符串搜索通常不区分大小写,除非您使用 the BINARY operator 。这个条件可以重写为

OldData.Surname = LookupData.Surname
<小时/>

第二个JOIN条件是:

LookupData.ServiceNumber like concat('%',OldData.ServiceNumber,'%') 

LIKE 对性能不利,尤其是当开头有 % 时:因为 MySQL 索引通常是有序的,这会导致触发全面扫描,因为无法找到优化的搜索起点。在您的示例数据中,您似乎可以删除起始 %

使用 INSTR 可能不会提高性能。

您可以尝试使用正则表达式,例如:

LookupData.ServiceNumber REGEXP OldData.ServiceNumber

如果你确实需要在大数据上进行两端搜索,MySQL 的方法是 Full-Text Search Functions 。这需要在服务编号列上创建一个 FULLTEXT 索引(并可能将它们从数字转换为文本),然后:

MATCH LookupData.ServiceNumber AGAINST OldData.ServiceNumber

关于Mysql LEFT JOIN 在两个参数上进行,在非常大的表上有一个精确匹配和一个 LIKE 匹配 - 性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54279959/

相关文章:

mysql - 尽管注释掉了安全文件 priv 部分,但仍出现“错误 1290 (HY000)”

mysql - 排除某行

java - SQL 中的选择语句、联接和重新调整查询用途

MySQL AND & OR 运算符

java - 外键约束在一对多上失败

php - 无法连接到 MySQL - 断电后丢失东西?

mysql - 如何以编程方式使整个规范套件快速失败

mysql - 通过与其他表进行比较(表差异)来删除和添加元素到表中

mysql - 在mysql中将列转换为行交叉表

mysql - Laravel - 验证用户输入的唯一值