Многие разработчики, работающие с 1С 7.7 на DBF-файлах, сталкиваются с проблемой медленного поиска по большим таблицам. Стандартный оператор LIKE при поиске «внутри строки» не использует индексы, что приводит к полному сканированию таблиц (full scan). Давайте разберем, как кардинально ускорить поиск, используя возможности современной библиотеки SQLite в связке с 1С.
Для решения задачи мы будем использовать компоненту 1SQLite с поддержкой модуля FTS5 (Full-Text Search версии 5). Этот движок позволяет индексировать данные методом триграмм (разбиение строк на сочетания по 3 символа), что делает поиск по подстроке практически мгновенным, даже если в базе сотни тысяч записей.
Сначала убедитесь, что ваша версия компоненты 1SQLite.dll собрана с поддержкой FTS5. Если нет, необходимо обновить библиотеку.
Поскольку мы работаем с DBF-данными 1С, нам нужно создать вспомогательную виртуальную таблицу в SQLite, которая возьмет на себя роль поискового индекса. Рассмотрим, как это сделать:
// Открываем базу данных в памяти или в файле
База = СоздатьОбъект("SQLiteBase");
База.Открыть("my_search_index.db3");
Запрос = База.НовыйЗапрос();
// Создаем виртуальную таблицу с использованием токенизатора 'trigram'
Запрос.ВыполнитьЗапрос("DROP TABLE IF EXISTS tri;");
Запрос.ВыполнитьЗапрос("
CREATE VIRTUAL TABLE tri USING fts5(
ID UNINDEXED,
DESCR,
VERSTAMP UNINDEXED,
tokenize='trigram'
);");
Здесь параметр tokenize='trigram' является ключевым: он указывает движку разбивать строки на трехсимвольные комбинации, по которым и будет происходить поиск.
После создания структуры необходимо перенести данные из справочника 1С в нашу виртуальную таблицу. Сделать это можно простым SQL-запросом:
Запрос.ВыполнитьЗапрос("
INSERT INTO tri(ROWID, ID, DESCR, VERSTAMP)
SELECT
Справочник_Номенклатура.ROWID,
Справочник_Номенклатура.ID,
Справочник_Номенклатура.DESCR,
Справочник_Номенклатура.VERSTAMP
FROM Справочник_Номенклатура;");
Рекомендуем также реализовать логику обновления данных. Если справочник меняется, можно использовать конструкцию INSERT OR REPLACE, проверяя изменения через VERSTAMP или другие поля версионности.
Теперь, когда индекс готов, поиск выполняется через оператор MATCH. Это работает в разы быстрее, чем LIKE.
// Пример поискового запроса
ТекстЗапроса = "SELECT ID, DESCR FROM tri WHERE tri MATCH 'ивНо';";
ТЗ = Запрос.ВыполнитьЗапрос(ТекстЗапроса);
Если вам нужно сочетание разных условий, можно использовать операторы AND и OR внутри строки MATCH. Это позволит находить записи по нескольким ключевым словам сразу.
Важный практический нюанс: стандартный токенизатор trigram отлично работает с тремя и более символами. Однако если пользователь вводит 1 или 2 символа, поиск по индексу может быть неэффективным. В таких случаях мы используем комбинированный подход:
// Совмещаем полнотекстовый поиск и обычный LIKE для коротких строк
ТекстЗапроса = "
SELECT * FROM tri
WHERE tri MATCH 'пив'
AND DESCR LIKE '%30%';";
В этом примере MATCH 'пив' мгновенно фильтрует основную массу данных через индекс, а LIKE '%30%' уточняет результат, работая уже с сильно сокращенным набором записей. Такой подход исключает «провисание» системы и экономит оперативную память.
SQLite-базу индекса не в памяти (":memory:"), а на диске. Это немного медленнее, но гораздо безопаснее с точки зрения потребления RAM.#, - или _, используйте настройки токенизатора ascii tokenchars при создании виртуальной таблицы.ПриЗаписи) или регламентным заданием, если объем данных огромен.Использование FTS5 превращает обычную DBF-базу 1С 7.7 в мощную поисковую систему. Этот метод — оптимальный баланс между скоростью работы и сложностью внедрения, позволяющий вдохнуть новую жизнь в старую платформу.