SQL Server搜索正确命名全文索引与LIKE + SOUNDEX

Mat*_*ert 5 sql-server lucene.net full-text-search fluent-nhibernate

我有一个拥有(目前)3500万行的人名的数据库.我需要知道快速搜索这些名称的最佳方法是什么.当前系统(不是我设计的),只是将索引的名字和姓氏列用于"LIKE"查询,并使用SOUNDEX的附加选项(虽然我不确定这实际上使用了多少).性能一直是该系统的一个问题,因此目前搜索限制为200个结果(运行时间仍然太长).所以,我有几个问题:

  1. 全文索引是否适用于专有名称?
  2. 如果是这样,查询专有名称的最佳方法是什么?(CONTAINS,FREETEXT等)
  3. 是否有其他系统(如Lucene.net)会更好?

仅供参考,我使用Fluent NHibernate进行数据访问,因此首选的方法将是首选.我目前正在使用SQL Server 2008.

编辑我想补充一点,我对解决方案非常感兴趣,这些解决方案可以解决常见拼写错误的名称,例如'smythe','smith',以及名字,例如'tomas','thomas'.

查询计划

  |--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)
Run Code Online (Sandbox Code Playgroud)

上面的SQL:

SELECT * FROM testdb.dbo.Test WHERE LastName LIKE 'WHITE%' AND FirstName LIKE 'THOMAS%'
Run Code Online (Sandbox Code Playgroud)

根据Mitch的建议,我创建了一个这样的索引:

CREATE INDEX IX_Test_Name_DOB
ON Test (LastName ASC, FirstName ASC, BirthDate ASC)
INCLUDE (and here I list the other columns)
Run Code Online (Sandbox Code Playgroud)

我的典型搜索(最后,第一次和出生日期)的搜索速度非常快.

Mit*_*eat 5

取决于你的LIKE查询的样子.

如果您正在搜索,LIKE '%abc%'则不能使用索引,而可以使用搜索LIKE 'abc%'索引时.此外,如果First和Last名称上的索引不"覆盖"发出的查询,则将执行密钥查找(书签查找)并显着影响性能.

您的索引是否定期重建?

你有一个示例查询计划吗?

更新:查询的覆盖索引是可用于执行WHERE条件的索引,并且还具有满足查询其余部分所需的所有列,例如SELECT列列表.

使用覆盖索引来提高查询性能

更新:即使您创建了一个复合索引(Lastname, Firstname) (因为lastname应该更具选择性),仍然需要在表聚簇索引中查找所有其他列('*'列列表).