为了账号安全,请及时绑定邮箱和手机立即绑定

使用 String.IndexOf 或 MS SQL 进行快速全文搜索

使用 String.IndexOf 或 MS SQL 进行快速全文搜索

C#
蝴蝶不菲 2022-09-04 16:24:15
我有一个情况,我需要一个超快速的全文通配符搜索。以前,我只使用SQL存储过程,该过程将对具有多个联接的表执行搜索,并使用查询,但是对于几百万条记录,它非常慢。LIKE '%searchTerm%'我尝试过在SQL中进行全文索引和搜索,但是,这似乎不起作用,因为它会在单词上中断,但我需要搜索字符串的中间。更改为一个新的 SQL 存储过程,该过程将所有搜索字段连接成一个字符串,并使用对象 ID 的另一列返回该字符串 - 然后将整个对象作为 C# 中的 a 缓存(特别是作为 C# 中的静态对象),并使用检查搜索字符串的逻辑似乎大大提高了性能(从大约 10 秒增加到大约 100 毫秒)。List<>AppPoolIndexOf()我担心的是,这是否是一个糟糕的方法,或者是否有更好的方法?创建要与对象 ID 关联的搜索字符串的新 SQL 存储过程如下所示:CREATE PROCEDURE [dbo].[Search_GetLookupTable]ASBEGIN    SELECT        ObjectId,        (Name + ' ' + OtherName + ' ' + ep.SomethingElse + ISNULL(            (            SELECT                    ' ' + twl.SomeBindingName                FROM                    TableWithLotsOfBindings twl                WHERE                     twl.ObjectId = e.ObjectId                FOR XML PATH('')            )        , '')) AS SearchString,        ep.LastActionDateTime AS OrderDate    FROM        ObjectTable e        INNER JOIN ObjectMetaData ep ON ep.ObjectId = e.ObjectIdEND GO然后,这会被加载到具有 and 的模型中。然后,我将它保存到搜索中的属性中,然后跟踪上次加载并每隔10分钟左右回收一次。List<>ObjectIdSearchStringstaticclassDateTime我最初也将其保存到分布式内存中缓存中,但是,性能非常差,序列化和传输数据。private static readonly List<GlobalSearchLookupModel> _CachedSearchLookupModel = new List<GlobalSearchLookupModel>();private static DateTime _CacheSearchLookupModelDateTime = DateTime.MinValue;List<GlobalSearchLookupModel> lookupModels = _CachedSearchLookupModel.Value;if (lookupModels == null){   lookupModels = SqlClass.SearchLookupTable();   _CachedSearchLookupModel.Value.Clear();   _CachedSearchLookupModel.Value.AddRange(lookupModels);   _CachedSearchLookupModelDateTime = DateTime.UtcNow;}
查看完整描述

2 回答

?
郎朗坤

TA贡献1921条经验 获得超9个赞

据我所知,在任何现代SQL数据库中都没有这样的解决方案。它们根本不是为像您这样的用例而设计的。

对于这样的解决方案,你真的需要看看像弹性搜索Azure搜索这样的解决方案,即使是那些需要你使用特殊构造和过滤器来实现纯通配符搜索功能的解决方案。


查看完整回答
反对 回复 2022-09-04
?
HUX布斯

TA贡献1876条经验 获得超6个赞

您可以尝试使用以下想法在SQL中构建自己的searchindex:


假设您的表是


MyTable(Id bigint Primary Key, Text nvarchar(max))


,其中是要在其中搜索的列。Text


然后构建一个表


IndexTable(TextIndex nvarchar(max) Primary Key, Id bigint)

,外键为 。IdMyTable


现在,您可以使用 MyTable 中包含的文本的所有后缀填充该表。


现在可以重写查询


SELECT * 

FROM MyTable 

WHERE Text LIKE '%searchTerm%'


to


SELECT * 

FROM MyTable 

WHERE Id IN (SELECT Id FROM IndexTable WHERE TextIndex LIKE 'searchTerm%')

(此查询也可以使用联接编写,但随后可能会导致重复)


这应该是一个有效的查询,因为可以使用索引表的PK索引。LIKE 'searchTerm%'


最后要注意的是,您可以使用触发器使该表保持最新状态。


查看完整回答
反对 回复 2022-09-04
  • 2 回答
  • 0 关注
  • 108 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信