Mysql 如何优化此Levenshtein距离计算
Mysql 如何优化此Levenshtein距离计算,mysql,levenshtein-distance,Mysql,Levenshtein Distance,表a约有8000行,表b约有250000行。如果没有levenshtein函数,查询只需不到2秒钟。包括该功能后,大约需要25分钟 SELECT * FROM library a, classifications b WHERE a.`release_year` = b.`year` AND a.`id` IS NULL AND levenshtein_ratio(a.title, b.title) >
表a
约有8000行,表b
约有250000行。如果没有levenshtein
函数,查询只需不到2秒钟。包括该功能后,大约需要25分钟
SELECT
*
FROM
library a,
classifications b
WHERE
a.`release_year` = b.`year`
AND a.`id` IS NULL
AND levenshtein_ratio(a.title, b.title) > 82
我假设
levenshtein_ratio
是您编写的函数(或者可能包含在其他地方)。如果是这样的话,数据库服务器将无法在使用索引的正常意义上对此进行优化。因此,这意味着它只需要为其他连接条件产生的每个记录调用它。对于内部联接,这些表的大小可能会非常大(最大值为8000*250000=20亿)。您可以使用以下命令检查需要调用它的总次数:
SELECT
count(*)
FROM
library a,
classifications b
WHERE
a.`release_year` = b.`year`
AND a.`id` IS NULL
这就是为什么它很慢的原因(并不是如何优化它的问题的答案)。要优化它,您可能需要向联接条件添加额外的限制因素,以减少对用户定义函数的调用次数。更改查询以使用正确的联接(自1996年以来,语法一直存在) 此外,您的所有levensrein条件都可能被移动到join条件中,这将为您带来性能优势:
SELECT *
FROM library a
JOIN classifications b
ON a.`release_year` = b.`year`
AND levenshtein_ratio(a.title, b.title) > 82
WHERE a.`id` IS NULL
此外,确保b年有一个指数:
create index b_year on b(year);
你提供的信息太少,无法真正帮助你 1) 我的第一个猜测是尝试创建其他WHERE条件,以减少要扫描的行数 2) 如果这是不可能的…鉴于表库和分类中的标题是已知的,一个想法是创建一个表,其中所有数据都已按如下方式计算:
TABLE levenshtein_ratio
id_table_library
id_table_classifications
precalculated_levenshtein_ratio
因此,您可以使用以下查询填充表:
insert into levenshtein_ratio select a.id, b.id, levenshtein_ratio(a.title, b.title) from library, classifications
然后您的查询将是:
SELECT
*
FROM
library a LEFT JOIN
classifications b ON a.`release_year` = b.`year`
LEFT JOIN levenshtein_ratio c ON c.id_table_library = a.id AND c.id_table_classifications = b.id
WHERE
a.`id` IS NULL
AND precalculated_levenshtein_ratio > 82
这个查询可能不会超过原来的2秒
此解决方案的问题在于,表a和表b中的数据可能会更改,因此您需要创建一个触发器以保持其更新。显然,我不知道您使用的是什么levenshtein算法,但您可以尝试优化levenshtein距离和