Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/26.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server 更快地查询大型(以百万计)数据_Sql Server_Tsql - Fatal编程技术网

Sql server 更快地查询大型(以百万计)数据

Sql server 更快地查询大型(以百万计)数据,sql-server,tsql,Sql Server,Tsql,我有两张桌子: Tbl1有两列:名称和状态 Tbl2具有名称和状态以及关于字段的附加列 我正在尝试将tbl1名称和状态与tbl2名称和状态匹配。我已经删除了所有精确匹配项,但我发现如果我可以使用一个标量函数来解释拼写错误和名称变化,那么我可以进行更多匹配,该函数比较两个名称,并返回一个整数,显示它们之间的匹配程度(数字越小,匹配效果越好) 问题在于Tbl1有超过200万条记录,而Tbl2有超过400万条记录——从Tbl2中的Tbl1中搜索一条记录大约需要30秒 我是否有办法安排数据或查询,以

我有两张桌子:

  • Tbl1有两列:名称和状态

  • Tbl2具有名称和状态以及关于字段的附加列

我正在尝试将tbl1名称和状态与tbl2名称和状态匹配。我已经删除了所有精确匹配项,但我发现如果我可以使用一个标量函数来解释拼写错误和名称变化,那么我可以进行更多匹配,该函数比较两个名称,并返回一个整数,显示它们之间的匹配程度(数字越小,匹配效果越好)

问题在于Tbl1有超过200万条记录,而Tbl2有超过400万条记录——从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

一种可能是添加一个列,其规范化名称仅用于匹配目的。你可以删除所有的空格,删除重音,用缩写的名字替换名字,用真名替换已知的昵称等等

您甚至可以按字母顺序对一个人的名字和姓氏进行排序,以允许两者进行交换

然后,您可以通过这个规范化名称列简单地连接这两个表

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

您正在按照最多50个不同的值联接条件联接2Mx4M行。难怪这么慢。你需要回到绘图板,重新定义你的问题。如果您真的想找出每个人与处于同一状态的其他人的“密切匹配”,那么请准备付出代价……

尝试从查询中删除标量函数ScoreHowCloseOfMatch。我怀疑这就是罪魁祸首。标量函数对性能很糟糕。取决于该函数的功能,它可以重写许多方法来提供相当大的帮助。两个过程如何?首先给每个表一个Soundex分数或类似的分数,然后加入它?你能让你的测试函数有nvarchar作为参数,即与表相同并重新运行吗?转换是昂贵的。很好的一点-这实际上是我为精确匹配所做的(我应该提到这一点)。我希望通过评分获得更多的匹配。区别在于,在插入和更新单个记录时会发生规范化,而as评分必须在查询过程中发生,因为您是在比较成对的记录。有很多可能的对:n*m(两个表的记录数的乘积)。