1

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
4

3 回答 3

1

我假设这levenshtein_ratio是您编写的函数(或者可能是从其他地方包含的)。如果是这样,数据库服务器将无法在使用索引的正常意义上对其进行优化。所以这意味着它只需要为其他连接条件产生的每条记录调用它。对于内部联接,对于这些表大小(最大为 8000*250000 = 20 亿),这可能是一个非常大的数字。您可以使用以下命令检查需要调用的总次数:

SELECT
      count(*)
   FROM
      library a,
      classifications b
   WHERE  
      a.`release_year` = b.`year`
      AND a.`id` IS NULL

这是对为什么它很慢的解释(并不是对如何优化它的问题的真正答案)。要对其进行优化,您可能需要向连接条件添加额外的限制因素,以减少对用户定义函数的调用次数。

于 2013-01-31T00:44:47.673 回答
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 中的数据可以更改,因此您需要创建一个触发器以使其保持更新。

于 2013-01-31T00:57:52.467 回答
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);
于 2013-01-31T00:49:10.400 回答