【问题标题】:How to make LIKE '%Search% faster in SQL Server如何在 SQL Server 中使 LIKE '%Search% 更快
【发布时间】:2016-07-26 21:00:12
【问题描述】:

我有一个占用大量时间的查询:-

 SELECT 
      p.CrmId,
      park.Name
 FROM
     Property p
 INNER JOIN
     Som som ON som.CrmId = p.SystemOfMeasurementId 
 LEFT JOIN
     Park park ON park.CrmId = p.ParkId
 WHERE 
     ((p.City like '%' + @search + '%' ) 
      OR (p.Address1 like '%' + @search + '%') 
      OR (p.Address2 like '%' + @search + '%' )
      OR (p.State like '%' + @search + '%' ) 
      OR (park.Name like '%' + @search + '%' ) 
      OR (p.ZipCode like '%' + @search + '%')
     )
     AND (@usOnly = 0 or (p.CrmCountryId = @USA_COUNTRY_ID))

我了解到,当我们使用 LIKE '%Search% 时,索引无法正常工作。

关于如何使这更快的任何想法?

【问题讨论】:

  • 你可能不走运
  • 你应该看看fulltext index/search这样的东西,你可能会得到更好的匹配和速度。
  • 即使使用 FTS,如果您在字符串的开头使用通配符搜索也会很慢。如果您使用搜索参数搜索每个单词的开头,那么 FTS 可以为您提供所需的速度。示例:带有值 Win 的 @search 应该匹配地址“123 Window lane”,而不是“123 LikWin”。请参阅此previous answer 作为如何使用 FTS 编写查询的示例,您将需要在列上构造目录和索引。您还可以调整索引的填充/搜索方式。
  • 全文搜索是您唯一的希望。当您使用前导通配符时,您消除了索引进行查找的能力。想想电话簿。如果您想要所有以“S”开头的姓氏,查找起来非常简单快捷。但是,如果您希望所有姓氏都包含“S”....那么您必须查看书中的每个条目以确定它是否匹配。这是对 sql 索引的高级解释。
  • @Igor FTS 可以设置为除索引单词之外的字符。

标签: sql-server


【解决方案1】:

你是对的......带有前导通配符的查询对于性能来说糟糕。为了解决这个问题,Sql Server 有一个叫做full text search 的东西。您为要搜索的每个列创建一个特殊的FULL TEXT Index,然后更新您的代码以使用CONTAINS keyword

SELECT 
  p.CrmId,
  park.Name
        from Property p
        inner join Som som on som.CrmId = p.SystemOfMeasurementId 
        left join Park park on park.CrmId = p.ParkId
  WHERE 
  (
       Contains(p.City, @search)
    or Contains(p.Address1, @search)
    or Contains(p.Address2, @search)
    or Contains(p.State, @search) 
    or Contains(park.Name, @search) 
    or Contains(p.ZipCode, @search)
 )
 AND (@usOnly = 0 or (p.CrmCountryId = @USA_COUNTRY_ID))

不幸的是,所有这些 OR 条件仍然可能使此过程变得相当缓慢,并且 FULL TEXT 并不适合像 City 或 State 这样的较短字符串,或者像这样投射宽网。您可能会发现通过与SolrElasticSearch 之类的工具集成,您会在这种搜索方面做得更好。除了编写更好更快的搜索之外,这些工具还可以帮助您创建合理的排名,以便按照有意义且与输入相关的顺序返回结果。

另一种策略是创建一个计算列,将您的地址和姓名文本连接到一个列中,然后通过一个 CONTAINS() 调用对该字段执行一个完整的文本索引。

【讨论】:

  • 您的 WHERE 子句可以简化为:CONTAINS((p.City, p.Address1, p.Address2, p.State, p.ZipCode), @search) OR CONTAINS(park.Name, @search).
  • FREETEXTCONTAINS() 强大,但CONTAINS() 比这更快...您可以使用全文搜索并添加Stoplist 阅读此内容:stackoverflow.com/questions/60293825/…
  • 与 OP 密切相关的一个非常重要的考虑因素是 LIKE %query% 将匹配字段中任何位置的子字符串。全文搜索、FREETEXTCONTAINS 不提供此功能。
  • @ttugates 这不是真的。 CONTAINS() 还将匹配字段中任何位置的子字符串。这就是它存在的全部原因。更重要的是,CONTAINS() 仍将使用索引,而 LIKE %query% 几乎总是完成搜索的绝对最慢的方式。
  • 我保持我评论的准确性,并且不同意它不真实。我也不同意“CONTAINS() 也将匹配字段中任何位置的子字符串。这就是它存在的全部原因。”一个带有 MS 文档链接的 SO:dba.stackexchange.com/questions/230064/…。撇开分歧不谈,将用户引向全文搜索是正确且有益的。我邀请任何有疑问的人谷歌full text search for substring
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多