MySQL 最长前缀匹配 100 万条记录与 3000 种可能性
Posted
技术标签:
【中文标题】MySQL 最长前缀匹配 100 万条记录与 3000 种可能性【英文标题】:MySQL longest prefix matching on 1 million records against 3000 possibilities 【发布时间】:2014-03-02 22:40:18 【问题描述】:我有一个包含大约 100 万个电话号码的表格和另一个包含大约 3000 个 ISD 代码(国家代码)的表格。现在我想将电话号码与所有这些 ISD 代码进行最长前缀匹配。 例如,在 ISD 表中:
1 US
1808 US (Hawaii)
如果电话号码现在是 1223244223,它应该返回美国,但如果它是 1808322353,它应该返回美国(夏威夷)。 以最佳性能实现这一目标的最佳方法是什么?
这是我目前所拥有的。不幸的是,对性能不满意,我想避免使用功能:
DELIMITER $$
CREATE DEFINER=`root`@`localhost` FUNCTION `isd`(telnum varchar(32)) RETURNS int(4)
BEGIN
RETURN (SELECT if(locate(isd, telnum)=1, (locate(isd, telnum)*length(isd)), 0) as score FROM tbl_ref_isd_v1 having score>0 order by score desc limit 1);
END
另外我还有这个不同的功能,好像快一点:
DELIMITER $$
CREATE DEFINER=`root`@`localhost` FUNCTION `isd_new`(telnum varchar(32)) RETURNS int(4)
BEGIN
RETURN (
select isd
from test.tbl_ref_isd_v1
where telnum like CONCAT(isd, '%')
order by length desc LIMIT 1
);
END
【问题讨论】:
【参考方案1】:这是一个可以满足您要求的查询:
select pn.*, max(ic.code)
from (select pn.*, ic.code, len(ic.code)
from PhoneNumbers pn join
ISDCodes ic
on pn.phonenumber like concat(ic.code, '%')
) pni
group by pn.phonenumber;
请注意,对于初始字符串,max()
有效,因为1808
大于1
,依此类推。
编辑:
在ISDCodes(code)
上建立索引。那么以下应该可以正常工作:
select pn.*, coalesce(ic5.code, ic4.code, ic3.code, ic2.code, ic1.code) as code
from PhoneNumbers pn left outer join
ISDCodes ic1
on left(pn.phonenumber, 1) = ic1.code left outer join
ISDCodes ic2
on left(pn.phonenumber, 2) = ic2.code left outer join
ISDCodes ic3
on left(pn.phonenumber, 3) = ic3.code left outer join
ISDCodes ic4
on left(pn.phonenumber, 4) = ic4.code left outer join
ISDCodes ic5
on left(pn.phonenumber, 5) = ic5.code;
您需要将连接添加到更长的ic.code
。
【讨论】:
您的逻辑是有效的,但速度很慢(在 180k 与 3700 isd 代码的小型记录集上 > 80 秒)。与需要 0,2s 的功能相比。不幸的是,该函数不会从 isd 表中返回整行(我更喜欢)。 第二个查询要快得多(也比函数快)。现在有没有办法独立于 ISDCode 长度?我有 1 到 9 位数字的代码。我添加了最多 9 个额外的连接,但我想知道我们是否可以以相同的性能使这个动态。对于我从 ISDCodes 表中获取的所有其他字段,我是否总是需要使用 coalesce 或者是否有更好的方法? @DavidLaroche 。 . .我认为您不能使这种动态化,并且仍然让查询使用使用基本 SQL 的索引。你可以使用prepare
语句来做到这一点。
我现在使用了 9 个单独的连接,这不应该经常改变,所以最后一切都很好而且很快。谢谢!以上是关于MySQL 最长前缀匹配 100 万条记录与 3000 种可能性的主要内容,如果未能解决你的问题,请参考以下文章
一个 VPC 与使用最长前缀匹配的两个 VPC 具有对等关系