索引SQL表以查找最佳匹配字符串的最佳方法
假设我有一个SQL表,它有一个索引SQL表以查找最佳匹配字符串的最佳方法,sql,sql-server,indexing,Sql,Sql Server,Indexing,假设我有一个SQL表,它有一个intPK列和一个nvarchar(max)。在nvarchar(max)列中,我有一组表项,它们都是这样的: SOME_PEOPLE_LIKE_APPLES SOME_PEOPLE_LIKE_APPLES_ON_TUESDAY SOME_PEOPLE_LIKE_APPLES_ON_THE_MOON SOME_PEOPLE_LIKE_APPLES_ON_THE_MOON_CAFE SOME_PEOPLE_LIKE_APPLES_ON_THE_RIVER . . .
int
PK列和一个nvarchar(max)
。在nvarchar(max)
列中,我有一组表项,它们都是这样的:
SOME_PEOPLE_LIKE_APPLES
SOME_PEOPLE_LIKE_APPLES_ON_TUESDAY
SOME_PEOPLE_LIKE_APPLES_ON_THE_MOON
SOME_PEOPLE_LIKE_APPLES_ON_THE_MOON_CAFE
SOME_PEOPLE_LIKE_APPLES_ON_THE_RIVER
.
.
.
SOME_ANTS_HATE_SYRUP
SOME_ANTS_HATE_SYRUP_WITH_STRAWBERRIES
这里有数百万行-假设我的目标是找到一个输入项重叠最多的行searchTerm
-因此在这种情况下,如果我输入一些人喜欢月亮山上的苹果
,返回的条目将是上表中的第三个条目,一些人喜欢月亮上的苹果
我有一个非常天真的SPROC,它贯穿整个表,如下所示:
SELECT DISTINCT phrase, len(phrase) l, [id] FROM X WHERE searchTerm LIKE phrase + '%'
-- phrase is the row entry being searched against
-- searchTerm is the phrase we're searching for
然后我按长度排序,只选择顶部
有没有一种方法可以加速这个过程,也许是通过建立索引
如果这令人困惑,请将其视为tableRowEntry+wildcard=searchTerm
我在MSSQL 2008上,如果这有什么不同的话如果你的NVARCHAR列a
上有一个像'Something%'这样的索引
-搜索将能够使用它,而且应该非常快
如果一开始有一个通配符,你就不走运了。但是,在你的情况下,这应该是可行的
您可以使用索引的持久计算列来存储字符串的长度。在这种情况下,通过过滤掉所有短字符串或长字符串,您可以极大地减少工作负载
如果搜索词中有某些词经常出现,但并非无处不在,则可以再次使用边栏并进行筛选,如和inlcudepople=1和IncludeMOON=1
更新
这里有一个例子
CREATE TABLE Phrase(ID INT IDENTITY
,Phrase NVARCHAR(100)
,PhraseLength AS LEN(Phrase) PERSISTED);
CREATE INDEX IX_Phrase_Phrase ON Phrase(Phrase);
CREATE INDEX IX_Phrase_PhraseLength ON Phrase(PhraseLength);
INSERT INTO Phrase
VALUES
('SOME_PEOPLE_LIKE_APPLES')
,('SOME_PEOPLE_LIKE_APPLES_ON_TUESDAY')
,('SOME_PEOPLE_LIKE_APPLES_ON_THE_MOON')
,('SOME_PEOPLE_LIKE_APPLES_ON_THE_MOON_CAFE')
,('SOME_PEOPLE_LIKE_APPLES_ON_THE_RIVER')
,('SOME_ANTS_HATE_SYRUP')
,('SOME_ANTS_HATE_SYRUP_WITH_STRAWBERRIES');
DECLARE @SearchTerm NVARCHAR(100)=N'SOME_PEOPLE_LIKE_APPLES_ON_THE_MOON_MOUNTAIN';
--这使用索引(对照执行计划检查)
--这可能更好,检查您的高行数
SELECT TOP 1 *
FROM Phrase
WHERE Phrase=LEFT(@SearchTerm,PhraseLength)
ORDER BY PhraseLength DESC;
GO
--清理
这里的最佳解决方案是创建全文搜索索引: 全文搜索针对此任务进行了优化,创建索引后,您可以使用包含全文功能的全文查询来高效查找匹配项:
SELECT DISTINCT phrase, len(phrase) l, [id] FROM X WHERE CONTAINS(phrase, searchPhrase)
全文搜索不仅允许通过查询提示进行自定义优化,如
OPTIMIZE FOR
,还允许搜索词中的AND AND OR等停止词,以及各种其他文本搜索优点,如能够自动查找同一单词的拼写变体并按相关性过滤等 你的查询应该使用searchTerm
上的索引,假设phrase
确实是一个常量参数。Matt,请参见我的更新示例…IMHO,OP无法筛选太长或太短的结果,因为他正在寻找最接近的匹配项。如果最接近的匹配在长度上不是完全匹配怎么办?@KamilG。嗯,有必要定义最近的。。。应该对过长的字符串进行分类——至少我是这样理解的……我相信当搜索词只有一个匹配项,并且它的长度与搜索短语的距离很大时,会出现边缘情况,但它仍然应该考虑到这一点。例如:搜索短语len=10,只找到一个len=1000的匹配项。@KamilG。我刚刚添加了一些示例(没有长度检查,这可能需要额外完成,具体取决于实际的业务案例)。谢谢,我理解了您之前的观点。一些对我不感兴趣的事情是在应用限制之前过滤掉——我相信有很多情况下你不能指定。
DROP TABLE Phrase;
SELECT DISTINCT phrase, len(phrase) l, [id] FROM X WHERE CONTAINS(phrase, searchPhrase)