Table a
有大约8,000行,table b
大约有250,000行。如果没有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
答案 0 :(得分:1)
我假设levenshtein_ratio
是您编写的函数(或者可能包含在其他地方)。如果是这样,数据库服务器将无法在使用索引的正常意义上优化它。所以这意味着它只需要为其他连接条件产生的每条记录调用它。使用内部联接,这可能是一个非常大的数字与这些表大小(最大8000 * 250000 = 20亿)。您可以使用以下方法检查需要调用的总次数:
SELECT
count(*)
FROM
library a,
classifications b
WHERE
a.`release_year` = b.`year`
AND a.`id` IS NULL
这解释了为什么它很慢(不是真正回答如何优化它的问题)。要对其进行优化,您可能需要在连接条件中添加其他限制因子,以减少对用户定义函数的调用次数。
答案 1 :(得分:1)
您提供的信息太少,无法真正帮助您。
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中的数据可能会发生变化,因此您需要创建一个触发器以使其保持更新。
答案 2 :(得分:0)
更改您的查询以使用正确的连接(语法自1996年以来一直存在)。
此外,您的所有levensrein条件都可能会进入连接条件,这会给您带来性能优势:
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.year上有索引:
create index b_year on b(year);