2016-02-29 45 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行。难怪这很慢。您需要返回绘图板并重新定义您的问题。如果你真的想弄清楚的每一个身体的“密切配合”与大家在相同的状态意外的话,要准备付出代价......