【问题标题】:SQL Server Performance tips for like %类似 % 的 SQL Server 性能提示
【发布时间】:2014-03-04 07:14:13
【问题描述】:

我有一个包含 5-1000 万条记录的表,其中包含 2 个字段

示例数据

Row  Field1   Field2
------------------
1    0712334  072342344
2    06344534 083453454
3    06344534 0845645565

给定 2 个变量

variable1 : 0634453445645
variable2 : 08345345456756

我需要能够尽快查询表以获得最佳匹配

上面的例子会产生 1 条记录(例如第 2 行)

查询数据库匹配的最快方法是什么?

注意:数据和变量总是采用这种格式(即总是一个数字,可能有也可能没有前导零,并且字段不是唯一的,但是两者的组合将是)

我最初的想法是做这样的事情

Select blah where Field1 + "%" like variable1 and  Field2 + "%" like variable2

如果不正确,请原谅我的伪代码,因为这更像是一个事实调查任务。不过我想我在球场上。

注意:我认为任何索引都无济于事,但我猜基于内存的表会加快速度。

谁能想到解决问题的更好方法?

【问题讨论】:

  • 虽然所有答案都帮助了我,但我认为@Mikael Eriksson 的答案让我在这个阶段最接近,通过 SQL 调优顾问考虑计划和索引

标签: sql-server performance sql-like


【解决方案1】:

您可以通过像这样的查询在Field1 上的索引上查找计划。

declare @V1 varchar(20) = '0634453445645'
declare @V2 varchar(20) = '08345345456756'

select Field1,
       Field2
from YourTable
where Field1 like left(@V1, 4) + '%' and
      @V1 like Field1 + '%' and
      @V2 like Field2 + '%'

它对Field1 的前四个字符进行范围查找,并在残差谓词中使用Field1Field2 的完整比较。

【讨论】:

  • 哇,这就是我一直在寻找的那种聪明,你认为这与 alzaimars 的答案相比(性能)如何?
  • @Saruman 你必须测试你的数据。我确实认为我的查询更容易构建,因为您不必使用传入的变量生成 in 子句。
  • 我非常喜欢你的方法。感谢这个解谜的新思路。
【解决方案2】:

没有性能提示。就这么简单。

%somethin% 是表扫描,由于开头 %,未使用索引。全文索引不起作用,因为它不是您要查找的全文,而是单词的一部分。

获得更快的机器来处理表扫描和非规范化是您唯一能做的事情。在一台像样的计算机上,5-1000 万行应该足够快。不需要基于内存的表 - 只需足够的 RAM 来缓存该表。

差不多就是这样。要么找到摆脱初始 % 的方法,要么让硬件(主要是内存)足够快来处理这个问题。

或者 - 在 sql server 之外处理它。将 5-10 百万行加载到搜索服务中并使用更好的数据结构。通用的 SQL 必须做出妥协。但同样,部分匹配会杀死几乎大多数方法。

【讨论】:

  • 谢谢或您的回复,幸运的是我只需要一些我认为更快的东西,但是我认为由于数据的性质,我可以使用反向整数(不要问我如何) 或者另一种方法。虽然我有点期待这种答案,再次感谢
  • 他要求的不是“%foo%”搜索,而是一种“反向开头”。所以我想一种优化的可能性。
【解决方案3】:

Postgres 有三元组索引http://www.postgresql.org/docs/current/interactive/pgtrgm.html

也许 SQL Server 有类似的东西?

【讨论】:

  • 我曾经在 SQL-Server 上的一个表上尝试 3-gram,该表有 6 个 Mio 行,其中包含音乐标题和歌手/乐队名称。生成的 Trigram 表包含大约 100 个 mio 条目,搜索很痛苦。我切换到全文。但是,这在这种情况下是不合适的。
  • 很有趣,但是我不确定 trigram 是否最适合这个问题,即使它是在 SQl Server 中实现的,不过还是感谢您的意见
【解决方案4】:

“Field1”和“Field2”列中最短的长度是多少?将此号码称为“N”。

然后创建一个 select 语句,它要求从长度为 N 的第一个字符开始到每个变量的长度的所有子字符串。示例(例如,N=10)

select distinct * from myTable 
where Field1 in ('0634453445','06344534456','063445344564', '0634453445645')
  and Field2 in ('0834534545','08345345456','083453454567', '0834534545675','08345345456756')

编写一个为您创建查询的小脚本。当然还有很多需要优化的地方,但这需要(恕我直言)改变你的表结构,我可以想象这是你不想要的。至少你可以快速尝试一下。

此外,当您在 SSMS 中尝试此方法时,您应该包含查询计划。查询计划将为您提供如何组织索引的良好提示。

【讨论】:

  • Hrm,最短的组合是 4 个字符,最长的大约是 9 个,我绝对可以做一些基准测试,看看这是否会带来一些性能提升,我会使用 linq,所以这很容易实现我'我猜
猜你喜欢
  • 2011-06-29
  • 1970-01-01
  • 1970-01-01
  • 2020-02-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多