我正在尝试使用我在'net上找到的levenshtein算法来计算与搜索词最接近的值。为了实现模糊项匹配。我当前的查询运行大约45秒。我希望我可以优化它。我已经为我计算出levenshtein值的字段添加了索引。我发现的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秒来处理它当前不可用。这只是一小部分记录,一旦我完成处理输入文件,它将构成整个数据存储。提前谢谢。
答案 0 :(得分:5)
如果您希望它运行得非常快,请考虑在C#中创建一个dll。它会将你的速度提高150%;)
以下是我的博客,向您解释如何操作。
答案 1 :(得分:2)
您应该阅读此主题和那些链接:http://www.vbforums.com/showthread.php?t=575471