Быстрый поиск телефонов

Как двадцати операторам, не подвешивая друг друга, быстро находить телефонный номер по первым продиктованным цифрам, когда база номеров — от 50 тыс…

Потратил час на спор с клиентом, что 1С работает медленнее, чем его база на Oracle, поэтому, обеспечить одновременную, безглючную работу нескольких операторов, чтобы они, вводя номер телефона, по первым цифрам получали в выпадающем списке подходящие номера, нельзя… Все бы ничего, но

1. номеров может быть много… десятки тысяч… сеть пиццерий в Санкт-Петербурге, как ни как

2. мое неумение решить эту проблему грозило срывом хорошего договора

В конечном итоге, убедили клиента, что, хотя это и сложно, но проблему решим. Договор заключили. А вечером действительно решили вопрос 🙂

Всего-то нужно было — посмотреть на вопрос не глазами клиента а нашими, т.е., программистов. Чем грузится база? Запросами к ней и блокировками таблиц. Значит, нужно большую часть работы повесить не на сервер, а на клиентское приложение! 

И так, простой метод:

1. по первой цифре отбираем в запросе нужные нам номера

2. все последующие цифры — это запрос не к базе, а к списку уже отобранных нами номеров

Осталось немного «косметики». Проблема: пока вводятся цифры в поле ввода, никакая обработка ожидания не срабатывает. Как быть? Тот франч, что был до нас и потерял этот заказ, не предложил решения.  

Но нечего баловать операторов полями ввода и выпадающими списками, дадим им нечто лучшее, отдельную форму ввода. Мотивация — теперь появилась возможность работать с сенсорными экранами…

— У Вас нет сенсорных экранов? Но ведь будут однажды!

— Да, конечно когда-нибудь будут…

Как я люблю это наше «надо прозапас»! И приятно, что наша небольшая супер команда оказалась хитрее крупного франча с филиалами во многих городах… 🙂

В общем, просто делюсь хорошим настроением и небольшой фичей, которую, если у кого похожая задача возникнет, не придется делать самому. В прилагаемой базе сгенерировано 50 тыс. номеров. Проверьте скорость работы. Можно и в сети.

«Ну а как быть, если номеров несколько миллионов?» — спросит кто-то

Не страшно! (Наверное)

Вариантов вижу 2, по крайней мере.

1. Использовать дополнительные поля в справочнике телефонов для отбора с включенной сортировкой. В частности: «Первый символ», «Два первых символа», «Три первых символа». Наверное, стоит все-таки обращаться к базе, пока длина введенной части не более 3-х символов, а вот потом уже работать со сформированным списком. Но по поводу этого готов услышать «за» и «против»

2. Использовать локальную базу номеров, выгруженную в виде того же dbf, и обращаться к ней на клиентской машине. При этом, dbf-ок можно иметь несколько. Опять же, по первому (двум) символу в номере.

13 Comments

  1. Magister

    Плюс за оригинальное решение проблемы поля ввода 🙂

    Собственно по алгоритму поиска — мне кажется, не стоит искать сразу после первой цифры. Вероятность, что при этом будет найден именно нужный телефон ничтожна, а нагрузку на базу это создаст немаленькую.

    Разве что это требование заказчика.

    Но и тогда лучше сделать типа ВЫБРАТЬ ПЕРВЫЕ 100.

    Reply
  2. Angeros

    Думаю что поле ввода можно было реализовать с клавиатуры… отдельно ввод, отдельно форма с вариантами… Ну и да я согласен с (1)номеров менее 4ех чисел ну хотя-бы 3ех… можно сделать.

    Reply
  3. khaoos

    А что не так с полем ввода? При наборе символов в поле ввода при малейшей задержке возникает событие «Автоподбор текста». Еще бы посоветовал навесить индекс на поле «номер телефона» в БД. Правда, в вашем решении он бесполезен, так как по одной цифре БД его точно не будет использовать.

    Reply
  4. mr zafod

    Тоже не вижу проблемы — есть автоподбор текста, есть менеджер временных таблиц для запросов, есть индексирование. Подобную задачу помню решал еще на 8.1 лет 5 назад и база номеров тоже была огромной (около 100 000) — все решилось за 3-4 часа без взрыва мозга. А там помимо выборки стояла еще и реальная проблема — формат номеров, коих было великое множество.

    Вы извините, но когда я вижу подобные «проблемы» — я начинаю понимать, почему у заказчиков такое предвзятое отношение к 1С, франчам и большинству специалистов 1С.

    Reply
  5. O-Planet

    (3) Ну, при использовании этого метода, конечно, будет все сложнее, но не намного. По крайней мере, нужно сравнивать ту строку, что сейчас в поле ввода с той, что в последний раз была отработана. Т.е., пара лишних переменных…

    Reply
  6. O-Planet

    (4) А что там 3-4 часа было делать?

    Проблемы, на самом деле, есть.

    Вот вопросы, которые я задаю себе, думая об этой задаче, и которые, я уверен, задаст заказчик впоследствии:

    1. Номера бывают городские и мобильные, как сократить ввод мобильного номера? Цифра «8», по сути, загонит все мобильные в мой список.

    2. И опять же, номер оператор… 8987 — это МТС у нас в городе. Несколько сот тысяч абонентов подключено на номер, начинающийся с этих цифр. Тут я соглашаюсь с (1): нужно подумать, как это оптимизировать.

    3. А что если номеров будет не 50, а 500 тыс? И заказчик уже на это намекал. Реально ведь, чтобы 500 тыс. питерцев заказали пиццу!

    Т.е., решение задачи требует оптимизации. И тут без выноса мозга, похоже, не обойтись.

    На самом деле, заказчик сформулировал задачу достаточно однозначно: общая база 1С (не управляемые формы), эмуляция локальной сети через интернет подключение, несколько десятков операторов. Телефонных номеров — много (весь С-П). Нужно чтобы все операторы могли работать одновременно, без каких-либо тормозов.

    Reply
  7. khaoos

    (6) можно посоветовать префиксные цифры для сотовых хранить в отдельном столбце. Там где делаю заказы обычно, «8»-ку для сотовых номеров не нужно указывать: логичная оптимизация :). При показе пользователю «склеивать» префикс и его номер. При поиске же префикс может послужить дополнительным фильтром для найденных номеров: но поиск по нему бы не запускался. Но если в базе уже много номеров, может быть рутинным решение выглядеть по внедрению этой оптимизации 🙂

    Reply
  8. mr zafod

    (6)О какой оптимизации идет речь? Пара лишних переменных в случае такой «тяжелой» задачи — думаю не проблема. Оптимизация здесь может быть только в том, чтобы:

    1) все номера хранить и вводить без восьмерки

    2) добавить измерения с индексацией по первым 3 и 3-6 символам номера

    Для выборки использовать автоподбор по первым 3, далее 6 символам (благо количество введенных символов можно узнать без проблем) использую запрос с ВТ и индексами (и менеджером, чтобы по 100 раз в базу не лазить).

    Все!!! Какая еще здесь может быть оптимизация? Есть желание — навешайте триггеров в postgre (oracle), потрясите планы запросов (хотя тут запрос линейный). Мы всегда ограничены платформой — не стоит об этом забывать!

    Reply
  9. cdb

    Проблема: пока вводятся цифры в поле ввода, никакая обработка ожидания не срабатывает.

    Для того что бы система дала обработать изменение после ввода любово символа (1-го, 2-го и т.д.) можно использовать элемент ActiveX к примеру MS Forms 2.0 TexBox. При каждом вводе символа будет отрабатывать событие ПриИзменении().

    Reply
  10. kuzev

    При наборе цифр сколько номеров телефонов должно быть в отобранном списке? Разумное значение какое?

    Мне кажется нет смысла «отображать» более нескольких десятков номеров. В этом случае можно завести отдельную таблицу (регистр) со значениями первых уникальных n-цифр (где n>3…5) номеров при условии, что таких номеров больше некого порога (например, 100). Сначала поиск осуществлять по ней, а как только значений не будет найдено можно лезть в общую таблицу, где записей с первыми n-цифр будет меньше порога.

    Reply
  11. kilokilo

    Телефоны — в текстовый файл. Регулярные выражения. Отработает за < 1 сек.

    Но оперативной памяти на локальной машине должно быть достаточно — весь текст в памяти.

    У меня 1С сыпалась при 2 000 000 строк на 2Гб оперативки на 32бит WinXP

    Если на БД — то вынести телефоны на SQL базу, работающую в ОЗУ.. MySQL, например. И организовать доступ к данным через web-сервис к этой базе из 1С. И, опять же, в запросе использовать регулярные выражения, что позволит искать данные в любой части номера..

    Если делать на 1С — можно попробовать иерархический справочник (иерархия элементов), 3 уровня.

    1й уровень — код страны, 2й — код города/оператора, 3й — телефон..

    Выборка на одно уровне иерархии происходит быстрее.

    В крайнем случае — создать у регистра, где хранят номера, индексированное поле, куда писать нормализованные номера — только циферки, без лишних пробелов, черточек, тире.. И запрос с инструкцией ПОДОБНО:

    ВЫбРАТЬ Номер Из Регистр ГДЕ Номер ПОДОБНО %ном% ИЛИ Номер ПОДОБНО %ном ИЛИ Номер ПОДОБНО ном%»

    Reply
  12. Evil Beaver

    И что, если просто проиндексировать поле Телефон и включить управляемые блокировки, то работает медленно? Там второй Пентиум на сервере?

    Reply
  13. zveruga56

    Неплохо бы предусмотреть поиск по подстроке.

    Набрал, к примеру, 888, а в списке:

    +79128882931

    +79878470888

    Для этого надо создать несколько индексных таблиц для отбора номеров по подстроке из 3,4,5 символов.

    При добавлении номера в базу — прописывать его и в индексные таблицы, со всеми возможными подстроками поиска.

    P.S. Пора уже с call-центром соединять.. 😉

    Reply

Leave a Comment

Ваш адрес email не будет опубликован. Обязательные поля помечены *