tsql - 尝试在 T-SQL 查询中使用 Levenshtein 距离 - 请帮助优化

标签 tsql query-optimization levenshtein-distance

我正在尝试使用我在网上找到的 levenshtein 算法来计算最接近搜索词的值。从而实现模糊词匹配。我当前的查询运行大约 45 秒。我希望我能优化它。我已经为计算编辑值的字段添加了索引。我发现的 levenshtein 函数可能不是最优化的,我不相信它的实现。这是该函数:

CREATE FUNCTION [dbo].[LEVENSHTEIN]( @s NVARCHAR(MAX), @t NVARCHAR(MAX) )
/*
Levenshtein Distance Algorithm: TSQL Implementation
by Joseph Gama

http://www.merriampark.com/ldtsql.htm

Returns the Levenshtein Distance between strings s1 and s2.
Original developer: Michael Gilleland http://www.merriampark.com/ld.htm
Translated to TSQL by Joseph Gama

Fixed by Herbert Oppolzer / devio
as described in http://devio.wordpress.com/2010/09/07/calculating-levenshtein-distance-in-tsql
*/
RETURNS INT AS
BEGIN

  DECLARE @d NVARCHAR(MAX), @LD INT, @m INT, @n INT, @i INT, @j INT,
    @s_i NCHAR(1), @t_j NCHAR(1),@cost INT

  --Step 1
  SET @n = LEN(@s)
  SET @m = LEN(@t)
  SET @d = REPLICATE(NCHAR(0),(@n+1)*(@m+1))
  IF @n = 0
  BEGIN
    SET @LD = @m
   GOTO done
  END
  IF @m = 0
  BEGIN
    SET @LD = @n
    GOTO done
  END

  --Step 2
  SET @i = 0
  WHILE @i <= @n BEGIN
    SET @d = STUFF(@d,@i+1,1,NCHAR(@i))        --d(i, 0) = i
    SET @i = @i+1
  END

  SET @i = 0
  WHILE @i <= @m BEGIN
    SET @d = STUFF(@d,@i*(@n+1)+1,1,NCHAR(@i))    --d(0, j) = j
    SET @i = @i+1
  END

  --Step 3
  SET @i = 1
  WHILE @i <= @n BEGIN
    SET @s_i = SUBSTRING(@s,@i,1)

    --Step 4
    SET @j = 1
    WHILE @j <= @m BEGIN
      SET @t_j = SUBSTRING(@t,@j,1)
      --Step 5
      IF @s_i = @t_j
        SET @cost = 0
      ELSE
        SET @cost = 1
      --Step 6
      SET @d = STUFF(@d,@j*(@n+1)+@i+1,1,
        NCHAR(dbo.MIN3(
          UNICODE(SUBSTRING(@d,@j*(@n+1)+@i-1+1,1))+1,
          UNICODE(SUBSTRING(@d,(@j-1)*(@n+1)+@i+1,1))+1,
          UNICODE(SUBSTRING(@d,(@j-1)*(@n+1)+@i-1+1,1))+@cost)
        ))
      SET @j = @j+1
    END
    SET @i = @i+1
  END      

  --Step 7
  SET @LD = UNICODE(SUBSTRING(@d,@n*(@m+1)+@m+1,1))

done:
  RETURN @LD
END

这是我正在使用的查询:

SELECT [Address], [dbo].[LEVENSHTEIN](@searchTerm, [Address]) As LevenshteinDistance
FROM Streets
Order By LevenshteinDistance

我不是 DBA,所以请原谅我对任何最佳实践的无知——这就是我来这里学习的原因:)。我真的不想在业务层中卸载此处理,并希望将其保留在数据层中,但只有 16k 条记录需要 45 秒来处理它目前不可用。这只是一小部分记录,一旦我处理完输入文件,它们将构成整个数据存储。提前致谢。

最佳答案

如果您希望它运行得非常快,请考虑在 C# 中创建一个 dll。它将使您的速度提高 150% ;)

这是我的博客,向您解释如何操作。

http://levenshtein.blogspot.com/2011/04/how-it-is-done.html

关于tsql - 尝试在 T-SQL 查询中使用 Levenshtein 距离 - 请帮助优化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4425561/

相关文章:

mysql - 我可以将此模式用于 where 子句的可选部分吗?

python - 在Python中的defaultdict中使用levenshtein距离作为键

postgresql - 提高 PARTITION BY 性能?

string - 编辑距离和三角不等式

python - 我可以找到相似的条目并将它们组合在一起吗?

sql - 有没有办法在 INSERT..SELECT 语句中有条件地使用默认列值?

sql - INT 数据库字段如何与 VARCHAR 类型进行比较

SQL 服务器 : Attempting to output a count with a date

sql-server - 在不同的设置上使 SQL Server 中的 Microsoft Access 表相同

mongodb - Mongodb优化查询