21

我有2列巨大的表:Id和标题。 Id是bigint,我可以自由选择Title列的类型:varchar,char,text,whatever。列标题包含随机文本字符串,如“abcdefg”,“q”,“allyourbasebelongtous”,最多255个字符。通过SQL中的子串查找字符串的最快方法?

我的任务是通过给定的子串获取字符串。子串也具有随机长度,可以是字符串的开始,中间或结尾。最明显的方式来执行它:

SELECT * FROM t LIKE '%abc%' 

我不在乎INSERT,我只需要做快速选择。我能做些什么来尽可能快地执行搜索?

我使用MS SQL Server 2008 R2,全文搜索将毫无用处,据我所见。

+11

欢迎来到数据库性能令人难以置信的美妙世界:-) – paxdiablo

+8

为什么全文搜索无用? –

+0

可能是子标记吗?如果你可以用空格,逗号或连字符分开单词,我有一个想法。让我知道。 – sgtz

回答

8

如果要使用比Randy的答案更少的空间,并且数据中有相当多的重复,可以创建N-Ary树数据结构,其中每个边都是下一个字符,并将每个字符串和尾随子串挂在数据中在上面。

您可以对节点进行一阶深度编号。然后,您可以为每条记录创建一个最多包含255行的表格,记录的Id以及树中与节点字符串或尾部子字符串匹配的节点ID。然后,当您执行搜索时,会找到表示要搜索的字符串(以及所有尾随子字符串)的节点ID并执行范围搜索。

+0

谢谢,我现在无法尝试你和Randy的解决方案,但我会尽快尝试。 – msergey

4

听起来像你排除了所有不错的选择。

你已经知道你的查询

SELECT * FROM t WHERE TITLE LIKE '%abc%' 

将不会使用索引,它会做一个全表扫描,每一次。

如果你是确保该字符串是在开始场,你可以做

SELECT * FROM t WHERE TITLE LIKE 'abc%' 

这将在标题中使用的索引。

您确定全文搜索无法帮到您吗?

根据您的业务需求,我有时会使用以下逻辑:

  • 做了一个“开始”查询(LIKE 'abc%')第一,这将使用索引。
  • 取决于是否返回任何行(或多少),有条件地转移到了“困难”的搜索,会做全扫描(LIKE '%abc%'

取决于你所需要的东西,当然,但我已经在最先显示最简单和最常见的结果的情况下使用了这种方法,并且在必要时才转向更难的查询。

+0

鉴于子字符串最有可能位于标题中,但我会尝试使用您的方法来衡量性能。 – msergey

+0

或集群索引扫描。可能没有什么重大区别。 – JeffO

+0

@Jeff - 这只是语义。聚簇索引扫描仅仅是一个具有聚簇索引(大多数表应该)的表上的“全表扫描”。无论哪种方式,它必须读取每条记录。 – BradC

13

如果您不关心存储空间,那么您可以使用部分标题条目创建另一个表格,以每个子字符串开始(每个普通标题最多255个条目)。

这样,你可以索引这些子串,只匹配到字符串的开头,应该大大提高性能。

+1

使该表成为一个集群化的非唯一索引...这可能与您使用原始SQL获得的一样好。 – sgtz

3

您可以在表格上添加另一个计算列:titleLength as len(title)PERSISTED。这将存储“标题”列的长度。在此创建一个索引。

另外,添加另一个名为ReverseTitle的计算列:Reverse(title)PERSISTED。

现在,当有人搜索关键字时,检查关键字的长度是否与titlelength相同。如果是这样,请执行“=”搜索。如果关键字的长度小于titleLength的长度,则执行LIKE。但首先做一个标题LIKE'abc%',然后做一个reverseTitle LIKE'cba%'。类似于Brad的方法 - 即只在需要时才执行下一个困难的查询。另外,如果80-20规则适用于你的关键字/子字符串(也就是说,如果大多数搜索是关于少数关键字的话),那么你也可以考虑做某种缓存。例如:假设您发现许多用户搜索关键字“abc”,并且此关键字搜索将返回带有20,22,24,25的ID的记录 - 您可以将其存储在单独的表中,并将其编入索引。 现在,当有人搜索新关键字时,首先查看此“缓存”表,以查看搜索是否已由更早的用户执行。如果是这样,则不需要再看主表。只需返回“缓存”表中的结果即可。

您还可以将上述内容与SQL Server TextSearch结合使用。 (假设你有一个合理的理由不使用它)。但是,您仍然可以先使用文本搜索来将结果集列入清单。然后对您的表运行SQL查询,以使用由TExt Search返回的ID作为参数以及关键字来获得确切的结果。

所有这些显然都假设你必须使用SQL。如果没有,你可以探索像Apache Solr这样的东西。

0

创建索引视图在sql创建索引中有一项新功能,您需要搜索并在搜索后使用该视图,以便提供更快的结果。

0
  1. 使用ASCII字符集群集索引炭柱。 由于ram和disk上的数据大小为 ,字符集会影响搜索性能。瓶颈往往是I/O。
  2. 您的专栏的字符长度为255个字符,因此您可以使用正常索引 您的字段而不是全文,这是更快。不要 在您的select语句中选择不必要的列。
  3. 最后,向服务器添加更多RAM并增加缓存大小
+0

我在其他答复中找到了N-Ary树方法。 –

+2

为什么它很搞笑? –

0

做一件事,使用特定列上的主键&以集群形式对其进行索引。

然后使用任何方法(外卡或=或任何),它将最佳的搜索,因为该表已经在集群的形式,搜索因此它知道在那里,他可以找到(因为列已经是排序的形式)

相关问题