2015-04-03 75 views
0

此過程需要10k行左右的分鐘。如何使用Levenstein算法優化SQL Server存儲過程?

如何讓它更快?

CREATE TABLE #TempTable 
(
     idl int, 
     idr int, 
     prof decimal(10,2), 
     sportkind nvarchar(50), 
     eventtype nvarchar(100), 
     eventname nvarchar(100), 
     eventdate datetime, 
     iscorridore bit 
) 

INSERT INTO #TempTable 
    SELECT 
     l.Id, r.Id, 
     (100.0/(1.0/l.CoeffValue + 1.0/r.CoeffValue) - 100.0), 
     r.SportKind, r.CoeffType, r.Team1 + '-' + r.Team2, r.EventDate, 
     dbo.CheckForCorridor(l.CoeffParam, l.CoeffKind, r.CoeffParam, r.CoeffKind) 
    FROM 
     Lines l, Lines r 
    WHERE 
     --l.BookmakerName != r.BookmakerName AND 
     l.EventDate = r.EventDate 
     AND l.SportKind = r.SportKind 
     AND (l.CoeffType = r.CoeffType OR (l.CoeffType is null AND r.CoeffType is null)) 
     AND dbo.CheckForFork(l.CoeffValue, r.CoeffValue) = 1 
     AND ((dbo.Levenstein(l.Team1, r.Team1) > 0.8 
      AND dbo.Levenstein(l.Team2, r.Team2) > 0.8) 
      OR (dbo.Levenstein(l.Team1, r.Team2) < 0.3 
       OR dbo.Levenstein(l.Team2, r.Team1) < 0.3) 
     ) 
     AND dbo.CheckSimpleCoeff(l.CoeffParam, l.CoeffKind, r.CoeffParam, r.CoeffKind) = 1 

INSERT INTO Forks (Name, Profit, EventDate, [Event], SportKind, EventType, LeftLine_Id, RightLine_Id, IsCorridore) 
    --поменять eventname 
    SELECT 
     eventname, prof, eventdate, eventname, sportkind, eventtype, 
     idl, idr, iscorridore 
    FROM 
     #TempTable temp 
    WHERE 
     NOT EXISTS (SELECT * FROM Forks c 
        WHERE temp.idl = c.LeftLine_Id 
        AND temp.idr = c.RightLine_Id) 

    DROP TABLE #TempTable 
END 

Levenstein是來自Simmetrics的CLR功能。

我嘗試找到一對符合上述過程規則的行,然後創建新條目並將它們寫入另一個表。

+2

[不良習慣踢:使用舊式JOIN](http://sqlblog.com/blogs/aaron_bertrand/archive/2009/10/08/bad-habits-to-kick-using-old-style- joins.aspx) - 在ANSI - ** 92 ** SQL標準中**舊式*逗號分隔的表*樣式列表已替換爲* proper * ANSI'JOIN'語法(**超過20年**之前),並且不鼓勵使用它 – 2015-04-03 11:34:06

+0

一個爲什麼你甚至在你不打算使用的行上計算Levenstein。最後你還沒有存在。 – Paparazzi 2015-04-03 12:22:34

回答

0

這太長了評論。

優化Levenshtein算法很困難。一種方法是在應用算法之前對結果進行預過濾。在SQL中,可以通過創建一個每個名稱和一個字母都有一行的新表,然後進行連接來完成此操作。舉例來說,如果你想有共通之處,那麼至少三個字母的名字:

select nl.name, nl2.name 
from nameletters nl join 
    nameletters nl2 
    on nl.char = nl2.char and nl.name <> nl2.name 
group by nl.name, nl2.name 
having count(*) >= 3; 

,或類似地,考慮Levenshtein距離只爲100名擁有最字母共同點:

select * 
from (select nl.name, nl2.name, rank(count(*)) over (partition by nl.name) as rnk 
     from nameletters nl join 
      nameletters nl2 
      on nl.char = nl2.char and nl.name <> nl2.name 
     group by nl.name, nl2.name 
     having count(*) >= 3 
    ) nn 
having rnk >= 100; 

這些都是啓發式方法,但它們可能有助於解決您的問題。

+0

我需要將每個條目與源表中的每個條目進行比較,Levenstein是參數之一。我如何選擇100個常用字母的名字? – user2642119 2015-04-03 11:51:22

+0

@ user2642119。 。 。這就是最後一個查詢所做的,假設你有一個表,每個名稱和一個字母都有一行。 – 2015-04-03 12:05:13