大表上的T-SQL和通配符字符串匹配性能

时间:2011-07-11 09:40:44

标签: c# tsql sql-server-2008 c#-4.0

我在使用T-SQL方面遇到了一些问题,我基本上处在一个需要运行大量查询的位置:

SELECT TOP 30 * FROM [table]
    WHERE firstfield IS NOT NULL
    AND secondfield IS NOT NULL
    AND (firstfield LIKE '%substring%' OR secondfield LIKE '%substring%')

这是从C#.NET程序运行的,SqlCommand的超时设置为90秒,对于大多数查询(搜索罕见或不存在的术语),它会超时。< / p>

这个问题当然是非常缓慢,但必须提取数据。获取后,所有返回的firstfieldsecondfield只会连接在一起(此更大的字符串将由程序存储和分析)。

我目前正在我的工作笔记本电脑上运行它,因为生成这些数据的生产服务器在运行数千个查询时速度过慢。在生产服务器上运行时,我的笔记本电脑(仅有4 GiB的RAM和常规的2.5英寸旋转硬盘驱动器)可以获得大约30%的结果,接近10%。

所以,有没有什么方法可以让我加快速度,或者最好还是暂停超时,让它运行几周直到完成?我考虑过只构建一个数据获取器程序,它只是将结果转储到一个单独的表中:

CREATE TABLE(
    id INT NOT NULL PRIMARY KEY IDENTITY,
    keyword VARCHAR(255) NOT NULL,
    returneddata VARCHAR(MAX), -- Or possibly a TEXT field.
)

这样我可以让fetcher程序运行,让我的主程序查询这个表。但说实话,我宁愿找出一种方法来使查询运行得更快(或另一种方式来进行查询)。我真的希望自己是个假人而且我错过了一些明显的方法来让这个跑得更快......

5 个答案:

答案 0 :(得分:4)

需要多快?有几个选项:使用索引来改善磁盘i / o(由于普通索引未针对搜索的子字符串进行优化,因此无法提供最佳性能)...或使用全文搜索(a设置更多的工作,但由于它们针对subn-string搜索进行了优化,因此可以为您带来巨大的性能提升。如果这是一个定期发生的操作,那么你会非常想要使用全文搜索,因为其他任何东西只会让你的问题更加困难。如果只是为了一次性工作,那么你可能逃脱基本索引(这取决于你得到的其他限制),但这绝不是保证...但是我会这里只是为了完整性。

第一个选项......你有这些列表的索引吗?如果你没有适当的索引,那么它将比它需要的速度慢得多,因为它必须直接从数据页中获取数据。如果没有,那么有两个选项:在(firstfield,secondfield)上创建一个复合索引,然后看看是否有任何作用。

或者创建两个索引,一个在(firstfield)上,另一个在(secondfield)上,并将查询拆分为两个查询,一个查询firstfield,另一个查询secondfield。

然而,由于普通索引没有针对子字符串搜索进行优化,因此这些都不会非常快:任何加速都只是由于磁盘I / O的改进,因为SQL Servfer不需要从磁盘读取尽可能多的数据找到匹配的行(它只是读取索引页而不是完整的数据页......但是一旦从磁盘上获取数据然后找到行,它仍然需要完成相同的工作量。)

如果您确实需要快速闪电,那么最好调查Full Text Search,这样您就可以使用CONTAINS关键字。这将允许您进行非常快速的子字符串搜索。

答案 1 :(得分:3)

您可以考虑启用全文,然后在查询中使用freetext而不是通配符 http://msdn.microsoft.com/en-us/library/ms176078.aspx

答案 2 :(得分:2)

如果字符串两边都有通配符(例如%x%而不是x%),则SQL Server无法使用任何统计信息来优化查询。

全文搜索是一种可能的解决方案,但我注意到LIKE未与记录的limitations on creating indexed views发生冲突。您可以创建一个视图并将其编入索引以获得相当快的结果。

答案 3 :(得分:1)

我强烈建议使用第二种方法。

您可以将“fetcher”程序作为后台任务/夜间等运行。

虽然您可以优化上述查询,但它永远不会像您提到的键/值方法那样高效,当然您可以正确地索引第二个表。

使用第二个表非常类似于非规范化,这是改进对用户请求或报告的响应的标准做法,因此您建议的不是任何方式。

在一天结束时,您的用户将会感受到更快的响应时间。

答案 4 :(得分:0)

由于这两个字段均为varchar(800),您可以执行以下操作:

SELECT TOP 30 * FROM [table]
    WHERE (
        coalesce(firstfield, '') LIKE '%substring%' OR
        coalesce(secondfield, '') LIKE '%substring%')

这对性能可能没什么帮助,但我会尝试两者并查看查询的执行计划。这应该告诉你在索引等方面使用了什么,我总是觉得非常有帮助。