使用 PATINDEX 对字符串搜索进行性能调整。
Performance tuning on String search using PATINDEX.
我有以下查询来使用 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'
数据详情:
DATABASE : LinkDB
Columns : 60
Data : 10 Millions
INDEX : [Employee Number],[Employee First Name],[Employee Last Name]
统计:
Query : Above query
Rows : 90,505
Time taken : 00:02:45
您可以尝试将 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''')
你可以看到,在你的情况下我们有远程扫描,然后过滤。第二个,过滤器通道丢失:
此外,如果您可以添加索引,则可以在 first
和 last
名称上添加索引,然后尝试先只选择需要返回的行:
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 , 只过滤聚簇索引。
我有以下查询来使用 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'
数据详情:
DATABASE : LinkDB
Columns : 60
Data : 10 Millions
INDEX : [Employee Number],[Employee First Name],[Employee Last Name]
统计:
Query : Above query
Rows : 90,505
Time taken : 00:02:45
您可以尝试将 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''')
你可以看到,在你的情况下我们有远程扫描,然后过滤。第二个,过滤器通道丢失:
此外,如果您可以添加索引,则可以在 first
和 last
名称上添加索引,然后尝试先只选择需要返回的行:
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 , 只过滤聚簇索引。