У меня есть база данных имен людей, которая имеет (в настоящее время) 35 миллионов строк. Мне нужно знать, что является лучшим методом для быстрого поиска этих имен. Текущая система (не спроектированная мной) просто индексирует столбцы с именами и фамилиями и использует запросы "LIKE" с дополнительной опцией использования SOUNDEX (хотя я не уверен, что это на самом деле часто используется). Производительность всегда была проблемой для этой системы, и поэтому в настоящее время поиск ограничен 200 результатами (что все еще занимает слишком много времени для запуска). Итак, у меня есть несколько вопросов:
- Хорошо ли работает полнотекстовый индекс для имен собственных?
- Если так, каков наилучший способ запроса имен? (СОДЕРЖИТ, FREETEXT и т. Д.)
- Есть ли какая-нибудь другая система (например, Lucene.net), которая была бы лучше?
Просто для справки, я использую Fluent NHibernate для доступа к данным, поэтому методы, которые будут работать с этим, будут предпочтительнее. Я использую SQL Server 2008 в настоящее время.
РЕДАКТИРОВАТЬ Я хочу добавить, что я очень заинтересован в решениях, которые будут иметь дело с такими вещами, как имена с орфографической ошибкой, например 'smythe', 'smith', а также с именами, например 'tomas ',' Томас '.
План запроса
|--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)
SQL для выше:
SELECT * FROM testdb.dbo.Test WHERE LastName LIKE 'WHITE%' AND FirstName LIKE 'THOMAS%'
Основываясь на совете Митча, я создал такой индекс:
CREATE INDEX IX_Test_Name_DOB
ON Test (LastName ASC, FirstName ASC, BirthDate ASC)
INCLUDE (and here I list the other columns)
Мой поиск теперь невероятно быстр для моего обычного поиска (последний, первый и дата рождения).