2016-02-29 87 views
-1

我有兩個表:查詢大(以百萬計)數據的速度更快

  • TBL1有2列:名稱和狀態

  • TBL2有有關字段名稱,狀態和其他列

我想匹配tbl1名稱和狀態與tbl2名稱和狀態。我已經刪除了所有完全匹配,但是我發現如果我可以通過使用比較2個名稱的標量函數來解釋拼寫錯誤和名稱變化,我可以匹配更多,並返回一個整數,表示它們匹配程度如何(號碼返回比賽越好)。

問題是Tbl1有超過2M條記錄,而Tbl2有超過4M條記錄 - 在Tbl2中從Tbl1搜索一條記錄大約需要30秒。

有什麼方法可以安排數據或查詢,以便搜索更快完成?

這裏的表結構:

CREATE TABLE Tbl1 
(
    Id   INT NOT NULL IDENTITY(1, 1) PRIMARY KEY, 
    Name  NVARCHAR(255), 
    [State]  VARCHAR(50), 
    Phone  VARCHAR(50), 
    DoB   SMALLDATETIME 
) 
GO 

CREATE INDEX tbl1_Name_indx ON dbo.Tbl1(Name) 
GO 
CREATE INDEX tbl1_State_indx ON dbo.Tbl1([State]) 
GO 


CREATE TABLE Tbl2 
(
    Id   INT NOT NULL IDENTITY(1, 1) PRIMARY KEY, 
    Name  NVARCHAR(255), 
    [State]  VARCHAR(50) 
) 
GO 

CREATE INDEX tbl2_Name_indx ON dbo.Tbl1(Name) 
GO 
CREATE INDEX tbl2_State_indx ON dbo.Tbl1([State]) 
GO 

下面是我測試,試圖排除功能複雜的樣本函數:

CREATE FUNCTION [dbo].ScoreHowCloseOfMatch 
    (
     @SearchString VARCHAR(200) , 
     @MatchString VARCHAR(200) 
    ) 
RETURNS INT 
AS 
    BEGIN 

     DECLARE @Result INT; 
     SET  @Result = 1; 
     RETURN @Result; 
    END; 

下面是一些樣本數據:

INSERT INTO Tbl1 
SELECT 'Bob Jones', 'WA', '555-333-2222', 'June 10, 1971' UNION 
SELECT 'Melcome T Homes', 'CA', '927-333-2222', 'June 10, 1971' UNION 
SELECT 'Janet Rengal', 'WA', '555-333-2222', 'June 10, 1971' UNION 
SELECT 'Matt Francis', 'TN', '234-333-2222', 'June 10, 1971' UNION 
SELECT 'Same Bojen', 'WA', '555-333-2222', 'June 10, 1971' UNION 
SELECT 'Frank Tonga', 'NY', '903-333-2222', 'June 10, 1971' UNION 
SELECT 'Jill Rogers', 'WA', '555-333-2222', 'June 10, 1971' UNION 
SELECT 'Tim Jackson', 'OR', '757-333-2222', 'June 10, 1971' 
GO 

INSERT INTO Tbl2 
SELECT 'BobJonez', 'WA' UNION 
SELECT 'Malcome X', 'CA' UNION 
SELECT 'Jan Regal', 'WA' 
GO 

以下爲查詢:

WITH cte as (
    SELECT t1Id = t1.Id , 
      t1Name = t1.Name , 
      t1State = t1.State, 
      t2Name = t2.Name , 
      t2State = t2.State , 
      t2.Phone , 
      t2.DoB, 
      Score = dbo.ScoreHowCloseOfMatch(t1.Name, t2.Name) 

    FROM dbo.Tbl1 t2 
    JOIN dbo.Tbl2 t1 
     ON t1.State = t2.State 
) 
SELECT * 
INTO CompareResult 
FROM cte 
ORDER BY cte.Score ASC 
GO 
+0

嘗試採取標量函數ScoreHowCloseOfMatch你的查詢。我懷疑這是罪魁禍首。標量函數對於性能來說很可怕。根據功能的不同,它可以重寫許多方法來顯着提供幫助。 –

+0

兩次傳球怎麼樣?首先給每個表Soundex評分或類似,然後加入呢? – SteveCav

+0

你可以讓你的測試函數有nvarchar作爲參數I.e.與表格相同並重新運行?轉換很昂貴。 –

回答

0

一種可能性是添加僅用於匹配目的的標準化名稱的列。你會刪除所有的空格,刪除口音,用簡寫的名字替換名字,用真實姓名替換已知的暱稱等。

你甚至可以按字母順序排序一個人的名字和姓氏,以便允許交換兩個。

然後,您可以簡單地通過此規範化名稱列連接兩個表。

+0

好點 - 這實際上是我爲完全匹配所做的(我應該提到這一點)。我希望通過得分來獲得更多的匹配。 – mwhib

+0

不同之處在於,在單個記錄上插入和更新時發生規範化,因爲在查詢過程中必須進行評分,因爲您正在比較記錄對。你有很多可能的配對:n * m(兩個表的記錄數的乘積)。 –

0
JOIN dbo.Tbl2 t1 
    ON t1.State = t2.State 

您正在加入最大50個不同值連接條件的2Mx4M行。難怪這很慢。您需要返回繪圖板並重新定義您的問題。如果你真的想弄清楚的每一個身體的「密切配合」與大家在相同的狀態意外的話,要準備付出代價......