【问题标题】:Performance tuning on String search using PATINDEX.使用 PATINDEX 对字符串搜索进行性能调整。
【发布时间】:2025-12-12 06:15:01
【问题描述】:

我有以下查询来使用 PATINDEX 搜索字符串。

查询:

SELECT [Employee First Name],[Employee Last Name],[Employee Middle Name],[Gender]............
FROM OPENQUERY([LinkDB],'SELECT [Employee First Name],[Employee Last Name],[Employee Middle Name],[Gender]............ FROM [LinkDB].dbo.[Employee]') 
WHERE ISNULL(PATINDEX('%Jack%',[Employee First Name]),'0') + ISNULL(PATINDEX('%Jack%',[Employee Last Name]),'0')  >= '1'

数据详情:

数据库:LinkDB
列数:60
数据:1000 万
INDEX : [员工编号],[员工名字],[员工姓氏]

统计:

查询:以上查询
行数:90,505
所用时间:00:02:45

【问题讨论】:

    标签: sql-server tsql sql-server-2008-r2


    【解决方案1】:

    您可以尝试将WHERE 子句添加到查询中。请注意,我稍微更改了代码以使其适用于我的环境:

    SELECT *
    FROM OPENQUERY([RMVNSQL01\INST1],'SELECT  [login], [FirstName], [LastName] FROM [smModel_20180807_UpdateTests_CORE].dbo.[SecurityUsers]') 
    WHERE ISNULL(PATINDEX('%emil%',[FirstName]),'0') + ISNULL(PATINDEX('%emil%',[LastName]),'0')  >= '1'
    
    SELECT *
    FROM OPENQUERY([RMVNSQL01\INST1],'SELECT  [login], [FirstName], [LastName] FROM [smModel_20180807_UpdateTests_CORE].dbo.[SecurityUsers] WHERE ISNULL(PATINDEX(''%emil%'',[FirstName]),''0'') + ISNULL(PATINDEX(''%emil%'',[LastName]),''0'')  >= ''1''') 
    

    您可以看到,在您的情况下,我们进行了远程扫描,然后进行过滤。第二种,filter pass 丢失了:

    另外,如果您可以添加索引,您可以在firstlast 名称上添加索引,然后尝试首先只选择需要返回的行:

    CREATE TABLE #EmployeesFiltered 
    (
        [EmployeeID] INT 
    );
    
    INSERT INTO #EmployeesFiltered ([EmployeeID])
    SELECT [EmployeeID]
    FROM [LinkDB].dbo.[Employee]
    WHERE ISNULL(PATINDEX('%Jack%',[Employee First Name]),'0') + ISNULL(PATINDEX('%Jack%',[Employee Last Name]),'0')  >= '1';
    
    SELECT *
    FROM [LinkDB].dbo.[Employee] A
    INNER JOIN  #EmployeesFiltered B
        ON A.[EmployeeID] = B.[[EmployeeID];
    

    即使您不允许依赖索引排序,当读取索引时,您将使用更少量的数据(您只需要读取所有用户 ID、名字和姓氏。然后拥有 ID,只需过滤聚集索引。

    【讨论】: