Sql server SQL Server搜索专有名称全文索引vs LIKE+;SOUNDEX
我有一个人名数据库,目前有3500万行。我需要知道快速搜索这些名字的最佳方法是什么。当前的系统(不是由我设计的),只是将名字和姓氏列编入索引,并使用“LIKE”查询,另外还可以选择使用SOUNDEX(尽管我不确定这是否实际使用得太多)。性能一直是这个系统的一个问题,因此目前搜索限制为200个结果(运行时间仍然太长)。因此,我有几个问题:Sql server SQL Server搜索专有名称全文索引vs LIKE+;SOUNDEX,sql-server,fluent-nhibernate,full-text-search,lucene.net,Sql Server,Fluent Nhibernate,Full Text Search,Lucene.net,我有一个人名数据库,目前有3500万行。我需要知道快速搜索这些名字的最佳方法是什么。当前的系统(不是由我设计的),只是将名字和姓氏列编入索引,并使用“LIKE”查询,另外还可以选择使用SOUNDEX(尽管我不确定这是否实际使用得太多)。性能一直是这个系统的一个问题,因此目前搜索限制为200个结果(运行时间仍然太长)。因此,我有几个问题: 全文索引对专有名称有效吗 如果是,查询专有名称的最佳方式是什么?(包含、自由文本等) 有没有其他更好的系统(比如Lucene.net) 仅供参考,我正在使用Fl
|--Parallelism(Gather Streams)
|--Nested Loops(Inner Join, OUTER REFERENCES:([testdb].[dbo].[Test].[Id], [Expr1004]) OPTIMIZED WITH UNORDERED PREFETCH)
|--Hash Match(Inner Join, HASH:([testdb].[dbo].[Test].[Id])=([testdb].[dbo].[Test].[Id]))
| |--Bitmap(HASH:([testdb].[dbo].[Test].[Id]), DEFINE:([Bitmap1003]))
| | |--Parallelism(Repartition Streams, Hash Partitioning, PARTITION COLUMNS:([testdb].[dbo].[Test].[Id]))
| | |--Index Seek(OBJECT:([testdb].[dbo].[Test].[IX_Test_LastName]), SEEK:([testdb].[dbo].[Test].[LastName] >= 'WHITDþ' AND [testdb].[dbo].[Test].[LastName] < 'WHITF'), WHERE:([testdb].[dbo].[Test].[LastName] like 'WHITE%') ORDERED FORWARD)
| |--Parallelism(Repartition Streams, Hash Partitioning, PARTITION COLUMNS:([testdb].[dbo].[Test].[Id]))
| |--Index Seek(OBJECT:([testdb].[dbo].[Test].[IX_Test_FirstName]), SEEK:([testdb].[dbo].[Test].[FirstName] >= 'THOMARþ' AND [testdb].[dbo].[Test].[FirstName] < 'THOMAT'), WHERE:([testdb].[dbo].[Test].[FirstName] like 'THOMAS%' AND PROBE([Bitmap1003],[testdb].[dbo].[Test].[Id],N'[IN ROW]')) ORDERED FORWARD)
|--Clustered Index Seek(OBJECT:([testdb].[dbo].[Test].[PK__TEST__3214EC073B95D2F1]), SEEK:([testdb].[dbo].[Test].[Id]=[testdb].[dbo].[Test].[Id]) LOOKUP ORDERED FORWARD)
根据Mitch的建议,我创建了如下索引:
CREATE INDEX IX_Test_Name_DOB
ON Test (LastName ASC, FirstName ASC, BirthDate ASC)
INCLUDE (and here I list the other columns)
对于我的典型搜索(last、first和birth date),我的搜索现在非常快。如果在“名字”和“姓氏”列上创建索引,那么使用LIKE的精确匹配搜索和前缀搜索将变得非常快 (在中,“如果LIKE的参数是一个不以通配符开头的常量字符串,则索引也可用于LIKE比较。”我认为MS SQL有类似的规则,但请查看MS SQL文档以确定。)
要加快SoundEx搜索,请存储新列的名字和姓氏的SoundEx版本,并在这些列上创建索引。取决于您喜欢的查询的外观 如果您正在搜索像“%abc%”这样的
,
则不能使用索引,而在搜索像“abc%”这样的时,可以使用索引。此外,如果名字和姓氏上的索引未“覆盖”发出的查询,则将执行键查找(书签查找),并显著影响性能
你的索引是否定期重建
您有一个示例查询计划吗
更新:查询的覆盖索引可用于执行WHERE条件,并具有满足查询其余部分(如选择列列表)所需的所有列
更新:即使您在(Lastname,Firstname)
上创建了一个复合索引(因为Lastname应该更具选择性),仍然需要在表聚集索引中查找所有其他列(“*”列列表)。我不太喜欢soundex。我认为新的算法迭代会更好,但是你把英语中的每个单词都散列成一个相当小的散列。随着时间的推移,这往往会产生大量错误匹配。我读过那个变音,它的后继双变音更好,但我没有直接的经验
米奇对
之类的的报道相当全面,所以我不打算重复了。索引将定期重建,可能每周重建一次。我正在以每天大约5000条的速度添加记录。哈,看起来当前系统根本没有使用“like”,显然太慢了。所以,我认为“abc%”应该是一种改进。你说的“覆盖”是什么意思?这真的很有帮助,米奇。我正在为您准备一个示例查询计划。那么,我应该创建一个包含我感兴趣的所有列的索引吗?我已经添加了查询执行计划。马修·塔尔伯特:嗯,这是一种权衡,取决于几个因素。宽索引通常不是一个好主意。您可以使用SQL Server 2005及以后版本的“包含部分创建索引定义”来创建覆盖索引。您还可以发布TSQL吗?谢谢您提供有关soundex的信息。
CREATE INDEX IX_Test_Name_DOB
ON Test (LastName ASC, FirstName ASC, BirthDate ASC)
INCLUDE (and here I list the other columns)