SQL查询-使用replace函数速度较慢

SQL查询-使用replace函数速度较慢,sql,sql-server,tsql,Sql,Sql Server,Tsql,我有一个查询需要很长时间,请参见下面 SELECT R.Email ,MAX(R.Id) ,MAX(R.Postcode) FROM ParsedCandidates PC INNER JOIN Results R ON REPLACE( REPLACE( REPLACE( REPLACE(R.[Resume], 'D:\documents\', '')

我有一个查询需要很长时间,请参见下面

SELECT R.Email
      ,MAX(R.Id)
      ,MAX(R.Postcode)
FROM ParsedCandidates PC
    INNER JOIN Results R
        ON REPLACE(
             REPLACE(
               REPLACE(
                 REPLACE(R.[Resume], 'D:\documents\', '')
               ,'D:\CMT\Resumes\', '')
             , 'internal_', '')
           , 'monster_', '')
      = REPLACE(
          REPLACE(
            REPLACE(
              REPLACE(PC.[File], 'D:\documents\', '')
            ,'D:\CMT\Resumes\', '')
          ,'internal_', '')
        , 'monster_', '') 
WHERE CONTAINS(PC.ParsedCV, '"Marketing Executive"')
    AND R.Email IS NOT NULL
    AND R.Email <> ''
    AND R.Postcode IS NOT NULL
    AND R.Postcode <> ''
    AND EXISTS (SELECT 1
                FROM Candidates_Sourcing CS
                WHERE CS.Email = R.Email
                    AND CS.Email IS NOT NULL
                    AND CS.Email <> ''
               )
GROUP BY R.Email;
候选资源表和结果表都有很多很多行

我知道替换功能将导致可搜索性问题,但我需要这样做以确保匹配


任何关于如何改进的想法

您所能做的就是在两个表上创建持久化列并对它们进行索引

ALTER TABLE Results ADD FixedPath AS REPLACE(
             REPLACE(
               REPLACE(
                 REPLACE([Resume], 'D:\documents\', '')
               ,'D:\CMT\Resumes\', '')
             , 'internal_', '')
           , 'monster_', '') PERSISTED

CREATE NONCLUSTERED INDEX ixResults_FixedPath ON Results (FixedPath) INCLUDE (...) WHERE (...)
包含索引,并且索引的位置可能取决于您的查询

如果不想更改表,可以在这两个表上创建索引视图,然后连接视图

CREATE VIEW v_Results 
WITH SCHEMABINDING
AS
SELECT R.Id
--   , ... other columns ...
     , REPLACE(
                 REPLACE(
                   REPLACE(
                     REPLACE(R.[Resume], 'D:\documents\', '')
                   ,'D:\CMT\Resumes\', '')
                 , 'internal_', '')
               , 'monster_', '') AS FixedPath
  FROM dbo.Resume R
 WHERE R.Email IS NOT NULL
   AND R.Email <> ''
   AND R.Postcode IS NOT NULL
   AND R.Postcode <> ''
GO
创建了这两个视图之后,就可以合并了

SELECT ...
  FROM v_Results R WITH (NOEXPAND)
  JOIN v_ParsedCandidates PC WITH (NOEXPAND)
    ON R.FixedPath = PC.FixedPath

NOEXPAND提示阻止SQL Server将视图扩展到基础查询中

如果REPLACE使查询不可搜索,那么数据引擎必须对整个表执行扫描。我猜您是在使用REPLACE函数删除路径并返回文件名?如果是这样的话,你真的应该把文件名作为一条单独的信息来存储;可以作为持久化计算列,也可以将路径和文件名存储为单独的列,然后进行适当的索引。然后您可以简单地使用一个类似R.ResumeFileName=PC.FileName的子句。计算机列是否意味着它可以被索引?做替换的费用会不会被转移到计算列,而且仍然很昂贵?为什么我说的是持久化计算列。它们可以被索引,顾名思义,该值作为持久值存储在表中。@MatthewStott是的-它正在移动成本。但是,您可以在插入/更新列时点击,也可以在每次运行此查询时点击。随着时间的推移,你认为哪一个更昂贵?再加上@SMor的观察,你不仅仅是在转移工作量,而是在将工作量分成小块。在执行查询期间,每次插入都会发生一行的替换工作,而不是同时发生数千或数百万次。将其视为一种分而治之的方法,而不是简单的提升和转移。
SELECT ...
  FROM v_Results R WITH (NOEXPAND)
  JOIN v_ParsedCandidates PC WITH (NOEXPAND)
    ON R.FixedPath = PC.FixedPath