#sql #search #database-design
Вопрос:
Мне нужно определить, есть ли имя в базе данных или нет (100% совпадение, но порядок имен безразличен). База данных содержит около 1.000.000 имен, результат: да/нет. Сервер имеет 32 ГБ оперативной памяти, используемой только для этого. Как быстро может прийти результат? Каждое имя может содержать до 100 прописных (A..Z) букв и/или цифр (0..9) и пробелов, например, Джон Смит 2-й. Большое спасибо за вашу помощь 🙂
Комментарии:
1. Вы имеете в виду, что хотите найти «Джон Смит 2-й», выполнив поиск точной строки, но также выполнив поиск «Смит 2-й, Джон» (т. Е. В другом порядке), но не при поиске «Джон Смит II» или просто «Джон Смит»?
2. Самым быстрым способом было бы проанализировать имена и разбить их на слова, сохранить их в отдельной таблице с FK в PK основной таблицы с кластеризованным индексом на имени, затем выполнить сравнение с критериями поиска, а затем выполнить поиск по отдельным поисковым запросам в этой отдельной таблице.
3. Дорогой Торстен, все в точности так, как ты написал.
4. Дорогой Стью, большое спасибо. Как вы оцениваете очень быстрое оборудование, как быстро это может примерно произойти? Пожалуйста, обратите внимание, что я не разработчик или ИТ-специалист, я просто хотел проверить самый быстрый способ, так как наш поставщик утверждает, что для одного имени требуется не менее 1-2 секунд
5. Существует слишком много переменных, чтобы дать вам какой-либо полезный ответ, вы даже не отметили свою платформу базы данных. Учитывая, что я только что получил миллион результатов поиска от Google в
Ответ №1:
Вы хотите найти 'John Smith the 2nd'
, выполнив поиск точной строки, но также выполнив поиск 'Smith the 2nd, John'
(т. Е. в другом порядке), но не при поиске 'John Smith II'
или 'John Smith'
или 'John Michael Smith the 2nd'
.
Это означает, что быстрый способ поиска имени-сохранить его нормализованным способом (например, все части упорядочены в алфавитном порядке, каждая отделена от следующей одним пробелом, точки и запятые удалены, все строчные буквы). Если вы проиндексируете это, СУБД очень быстро найдет имя с помощью двоичного поиска.
Как вы это сделаете, зависит от того, что предлагает ваша СУБД. В Oracle, например, я бы написал функцию базы данных для нормализации имени и написал индекс функции. Таким образом, таблица содержит только обычное имя ( 'John Smith the 2nd'
), но за кулисами СУБД проиндексировала нормализованное:
create index idx_name on mytable ( normalize_name(name) );
select * from mytable where normalize_name(name) = normalize_name(:input_name);
В другой базе данных вы можете вместо этого использовать вычисляемый столбец или даже иметь обычный столбец, который заполняется триггером и индексирует этот столбец. Но идея остается той же самой.
Без такого подхода СУБД пришлось бы вместо этого читать всю таблицу целиком. Миллион имен-это не так уж много, но их последовательное чтение все равно займет значительно больше времени, чем двоичный поиск по индексу.
Некоторые базы данных предлагают полнотекстовый поиск, но, поскольку вы ищете только точные совпадения (за исключением порядка слов), я ожидаю, что моя оценка будет быстрее.