|
Оптимизация скорости поиска номенклатуры запросом по наименованию. | ☑ | ||
---|---|---|---|---|
0
Повелитель
07.09.16
✎
06:56
|
Справочник номенклатура относительно не большой 255 000 товаров.
Заметил, что поиск по наименованию запросом составляет от 1 до 2 секунд. Поиск производим по справочнику списку номенклатуры. Вот запрос (время выполнения 1-2 секунды): ВЫБРАТЬ мНоменклатура.Ссылка КАК Ссылка, мНоменклатура.Наименование КАК Номенклатура ИЗ Справочник.Номенклатура КАК мНоменклатура ГДЕ мНоменклатура.Наименование ПОДОБНО "%Тщеслави%" Этот запрос (время выполнения 2-3 секунды, еще дольше, но это и было понятно, просто пишу для анализа): ВЫБРАТЬ мНоменклатура.Ссылка КАК Ссылка, мНоменклатура.Наименование КАК Номенклатура ИЗ Справочник.Номенклатура КАК мНоменклатура ГДЕ мНоменклатура.Наименование ПОДОБНО "%Тщеслави%" И мНоменклатура.Ссылка В ИЕРАРХИИ(&Ссылка) Вопрос почему так долго ищет по наименованию? Нет даже мысли как это можно оптимизировать. |
|||
1
Повелитель
07.09.16
✎
06:57
|
(0) Планируем 500 000 товаров, скорость еще думаю раза в 2 упадет при таком раскладе.
|
|||
2
Повелитель
07.09.16
✎
06:59
|
Причем у нас есть сайт 50 000 товаров, скорость самого запроса MySQL по наименованию десятые или сотые секунды.
|
|||
3
чувак
07.09.16
✎
07:04
|
(2) А что если через черный запрос?
|
|||
4
МешочекЗнаний
07.09.16
✎
07:05
|
(3) Это как?
|
|||
5
чувак
07.09.16
✎
07:05
|
(4) Запрос через com-объект СКЛ
|
|||
6
МешочекЗнаний
07.09.16
✎
07:07
|
(5) Извиняюсь что вопрос в чужой теме, но можно ссылку на статью как это использовать?
|
|||
7
Повелитель
07.09.16
✎
07:10
|
(3) Пока не рассматривали.
|
|||
8
Повелитель
07.09.16
✎
07:12
|
(7) Интересный вариант конечно.
|
|||
9
Повелитель
07.09.16
✎
07:13
|
Провел эксперимент.
Попробовал поможет ли менеджер временных таблиц. Загнал туда весь справочник номенклатуры, а потом искал по нему. Скорость одинаковая, я удивлен. Вот весь код из обработки: Перем МВТ; Перем ЗапросКэш; Процедура КнопкаВыполнитьНажатие(Кнопка) ЗапросКэш.Текст = "ВЫБРАТЬ | мНоменклатура.Ссылка КАК Ссылка, | мНоменклатура.Наименование КАК Наименование |ИЗ | КэшНоменклатуры КАК мНоменклатура |ГДЕ | мНоменклатура.Наименование ПОДОБНО ""%Тщеслави%"""; РезультатЗапроса = ЗапросКэш.Выполнить(); ТаблицаЗапроса = РезультатЗапроса.Выгрузить(); КонецПроцедуры Процедура ОсновныеДействияФормыЗагрузитьВКэш(Кнопка) ЗапросКэш = Новый Запрос; ЗапросКэш.МенеджерВременныхТаблиц = МВТ; ЗапросКэш.Текст = "ВЫБРАТЬ | мНоменклатура.Ссылка КАК Ссылка, | мНоменклатура.Наименование КАК Наименование |ПОМЕСТИТЬ КэшНоменклатуры |ИЗ | Справочник.Номенклатура КАК мНоменклатура | |ИНДЕКСИРОВАТЬ ПО | Наименование"; РезультатЗапроса = ЗапросКэш.Выполнить(); КонецПроцедуры Процедура ПриЗакрытии() МВТ.Закрыть(); КонецПроцедуры МВТ = Новый МенеджерВременныхТаблиц; |
|||
10
Повелитель
07.09.16
✎
07:14
|
(9) Вот обработка сама: https://yadi.sk/d/9M2UCJ04ur848
|
|||
11
Провинциальный 1сник
07.09.16
✎
07:18
|
"подобно" никак не соптимизируешь, если в начале стоит "%"
|
|||
12
Провинциальный 1сник
07.09.16
✎
07:19
|
(11) за исключением формирования специфического индекса по лексемам, как это сделано в механизме полнотекстового поиска
|
|||
13
чувак
07.09.16
✎
07:24
|
Как то так:
Connection = Новый COMОбъект("ADODB.Connection"); Connection.Open(стрПодключения); RS = Новый COMОбъект("ADODB.Recordset"); RS.Open("SELECT * FROM [BaseName].[dbo].[_Reference10] Пока RS.EOF() = 0 Цикл //ту что-то надо делать RS.MoveNext(); КонецЦикла; RS.Close(); Connection.Close(); |
|||
14
Провинциальный 1сник
07.09.16
✎
07:27
|
(13) А смысл переносить на прямые запросы? Узкое место тут - seq scan по таблице без индекса, ибо like начинается с "%".
|
|||
15
Jonny_Khomich
07.09.16
✎
07:28
|
ищи не каждую номенклатуру по отдельности, а весь список скопом.
|
|||
16
Повелитель
07.09.16
✎
07:36
|
(15) Как понять весь список?
|
|||
17
Jonny_Khomich
07.09.16
✎
07:39
|
(16) ты каждый раз ищешь по 1 номенклатуре? Надо искать сразу много?
|
|||
18
Повелитель
07.09.16
✎
07:41
|
(17) Операторы ищут, например по названию книги, в отбор может попасть несколько книг.
|
|||
19
Повелитель
07.09.16
✎
07:41
|
Вопрос про менеджер временных таблиц.
Когда делаешь ПОМЕСТИТЬ, данные где хранятся в памяти сервера или во временной таблице? Вроде помню что во временной таблице в SQL, но не уверен. Если во временной таблице, то понятно, почему скорость не увеличивается. |
|||
20
Провинциальный 1сник
07.09.16
✎
07:43
|
(19) Сервер в любом случае эффективно кэширует, и разницы нет, ибо для поиска надо пробежаться в среднем по половине всех записей. Решение проблемы - полнотекстовый индекс. Можно попробовать заюзать полнотекстовый поиск 1с. Ну или изобрести свой велосипед, чтобы не быть завязан на мутные 1совские алгоритмы..
|
|||
21
Повелитель
07.09.16
✎
07:44
|
(20) Спасибо, полнотекстовый поиск тоже рассмотрим.
|
|||
22
Провинциальный 1сник
07.09.16
✎
10:18
|
(21) Я бы делал так. Создал регистр сведений с двумя измерениями - Лексема и Ссылка. В подписке на событие "при записи" справочника Номенклатура создаю записи в этом регистре по каждому слову из наименования и ссылке на элемент справочника. Ну и первично обработкой заполнить этот регистр по существующим данным.
А дальше, при подборе по слову делаем запрос по измерению регистра, и вытаскиваем ссылку. |
|||
23
H A D G E H O G s
07.09.16
✎
10:45
|
(22) Отличный велосипед реализации полнотекстового поиска :-)
|
|||
24
Повелитель
07.09.16
✎
11:14
|
(22) Классный вариант, спасибо ))
|
|||
25
Fragster
гуру
07.09.16
✎
11:16
|
||||
26
Повелитель
07.09.16
✎
11:17
|
(25) Эх 19 августа ИТС закончился, только наверно в конце сентября новый оформим.
|
|||
27
Fragster
гуру
07.09.16
✎
11:23
|
||||
28
Fragster
гуру
07.09.16
✎
11:23
|
а вообще вся информация по полнотекстовому поиску есть в СП
|
|||
29
тарам пам пам
07.09.16
✎
11:32
|
Собственно да, почему для полнотекстового поиска не использовать механизм полнотекстового поиска?
И еще - 1с умеет сама по части строки искать (даже без полнотекстового поиска), попробуй в свойствах справочника на закладке "Поле ввода" установить способ поиска строки "Любая часть". Может 1с при этом какой-то более оптимальный запрос сгенерирует. |
|||
30
H A D G E H O G s
07.09.16
✎
11:34
|
(29)
"Может 1с при этом какой-то более оптимальный запрос сгенерирует." *facepalm |
|||
31
Повелитель
07.09.16
✎
11:35
|
(29) У нас обычные формы, способ поиска строки "Любая часть" это для управляемых по-моему.
|
|||
32
ViSo76
07.09.16
✎
11:37
|
(29) Запрос написал топикастер. 1С не будет переписывать запрос, да и что тут перепишешь в like?
Правильно подсказывают механизм полнотекстового поиска платформы использовать. На мой взгляд это самый оптимальный вариант. |
|||
33
тарам пам пам
07.09.16
✎
11:42
|
(30) ну почему сразу facepalm, 1с должна хотя бы ограничение на количество записей поставить. Плюс есть тот же CONTAINS, который вроде бы побыстрее LIKE работает.
|
|||
34
Метранпаж
07.09.16
✎
11:43
|
(33) Кому должна?
|
|||
35
Метранпаж
07.09.16
✎
11:44
|
а насчёт contains
мНоменклатура.Наименование ПОДОБНО "%Тщес%лави%" |
|||
36
xafavute
07.09.16
✎
11:47
|
(33) Ты наверно и планы этих запросов смотрел?
|
|||
37
H A D G E H O G s
07.09.16
✎
11:48
|
(33) чудес не бывает.
Это физика этого мира, ничего больше http://www.sql.ru/articles/mssql/2007/012302seekpredicates.shtml |
|||
38
H A D G E H O G s
07.09.16
✎
11:50
|
like %ЗначениеПоиска - это один в один аналог ситуации пропущенного поля поиска в составном индексе.
|
|||
39
Лефмихалыч
07.09.16
✎
11:56
|
там план проще некуда
<1C> Index Seek( OBJECT:( [db].[dbo].Справочник.Номенклатура.[Индекс по Наименование, Ссылка] AS [T1]), SEEK:([T1].[Наименование] > [Expr1004] AND [T1].[Наименование] < [Expr1005]), WHERE:([db].[dbo].Справочник.Номенклатура.[Наименование] as [T1].[Наименование] like [@P1] ) ORDERED FORWARD ) </1C> в нем нечего совершенствовать и ускорять. Если надо быстрее, придумывайте что-то с аппаратной частью. Ну, или еще лучше - глубоко-глубоко задумываться, а надо ли на самом деле часто такой лайк на сервер отправлять. |
|||
40
ptiz
07.09.16
✎
11:58
|
Сделать маленький регистр, где будет измерение - Ссылка на товар, и ресурс - Наименование.
По меньшей таблице быстрее отработает. |
|||
41
ptiz
07.09.16
✎
12:01
|
Еще можно добавить "ПЕРВЫЕ 10".
А остальные результаты - выдавать по требованию через отдельную кнопку "Показать еще". |
|||
42
xafavute
07.09.16
✎
12:02
|
(41) Это поможет, если первые 10 найдутся быстро, а если в самом конце, то нет
|
|||
43
Лефмихалыч
07.09.16
✎
12:02
|
(40) если у ресурса не включить индексирование, то будет только дольше. А, если включить, то будет так же
|
|||
44
ptiz
07.09.16
✎
12:06
|
(43) Нужен эксперимент. В справочнике Номенклатура, обычно десятки реквизитов, и таблица может быть на порядок меньше.
|
|||
45
Лефмихалыч
07.09.16
✎
12:10
|
(44) Запрос из сабжа генерит index seek по индексу, в котором только два поля. У справочника по индекс (наименование+Ссылка) генерится платформой автоматом, если наименование длиннее нуля. А вот ресурсы в индекс РС попадают только после включения у них индексирования. Соответственно, если у твоего РС будет индекс (Наименование+Ссылка), то в лучшем случае он даст точно такой же план и точно такую же производительность. В худшем - это будет table scan без производительности вообще.
|
|||
46
ViSo76
07.09.16
✎
12:23
|
Можно реализовать алгоритм с разбиением слова на буквы, с ссылками и указанием позиции в слове, и простым сгенерированным запросом вытаскивать нужную ссылку путём подсчёта их количества, но таблица будет очень большая
|
|||
47
ptiz
07.09.16
✎
12:41
|
(45) Да, наверное ты прав :)
Только наверное index scan ? |
|||
48
Повелитель
07.09.16
✎
12:55
|
(41) В рабочем запросе у нас стоит Первые 10, только цифра другая, я об этом в (0) писать не стал, так как на производительность это не влияет. Пробовали по всякому.
(40) Подобный вариант описан в (22), но я понял он работать не будет. Так как ускорение можно добиться если использовать "=", а там тоже придется использовать ПОДОБНО. |
|||
49
xafavute
07.09.16
✎
12:56
|
(47) Индекс скан - это вообще не использование индекса.
Просто этот индекс оказался кластерным |
|||
50
xafavute
07.09.16
✎
12:57
|
можно пойти не прием: переименовать все номенклатуру в стиле магистра йоду. Ключевые слова в начало
|
|||
51
Повелитель
07.09.16
✎
12:58
|
(44) Подобный эксперимент я проводил,
Если брать 2 реквизита Ссылка и Наименование, то от количества колонок в таблице из которой идет выборка, время выполнения запроса не сильно зависит. Время выполнения запроса увеличивается если выбирать не 2 поля Ссылка и Наименование, а допустим еще 10 других. |
|||
52
xafavute
07.09.16
✎
12:59
|
(51) план запроса так и не научился смотреть?
|
|||
53
Повелитель
07.09.16
✎
13:00
|
(52) Смотрю туда очень редко, так как примерно представляю какой 1с для SQL запрос подготовила. Повторюсь примерно.
|
|||
54
ptiz
07.09.16
✎
13:01
|
Чисто фантазия: все наименования склеить в большую хранящуюся в памяти строку, разделенную на блоки спецсимволом, и на неё натравить: или просто поиск подстроки, а если недостаточно - регулярные выражения. Но чтобы они возвращали номер блока.
Но при изменении наименования надо строку перестраивать. |
|||
55
Лефмихалыч
07.09.16
✎
13:05
|
(47) если ресурс не индексировать, то будет table scan, т.к. не будет индекса, по которому можно было бы искать
|
|||
56
Повелитель
07.09.16
✎
13:05
|
(54) В памяти в каком месте?
У нас еще есть сайт на 1С Битрикс, там технологии позволяют хранить кэш в памяти. В 1с даже не слышал о таких возможностях. Временные таблице, хранятся на диске. |
|||
57
Провинциальный 1сник
07.09.16
✎
13:05
|
(48) "Так как ускорение можно добиться если использовать "=", а там тоже придется использовать ПОДОБНО"
ПОДОБНО тоже использует индекс, если искать с начала слова. |
|||
58
Провинциальный 1сник
07.09.16
✎
13:06
|
(57) То есть с начала поля, не ставить в начале выражения %
|
|||
59
Повелитель
07.09.16
✎
13:07
|
(58) Понял, спасибо, проверил, быстро работает.
Тогда да (22) это вариант хороший. |
|||
60
Лефмихалыч
07.09.16
✎
13:08
|
любые оптимизаяйца должны начинаться с вопроса: "назачем это, что нуждается в оптимизации, вообще нужно?" Т.к. идеальная оптимизация объекта будет тогда, когда объекта вообще исчезнет , а функция его будет выполняться
|
|||
61
Torquader
07.09.16
✎
13:12
|
Обычно ищут части слов - соответственно - наименование разбит на слова и уже искать по таблице слов, потом полученную выборку из таблицы слов (там ссылки на номенклатуру) выбрать из таблицы номенклатуры.
Проблемы будут начинаться, если кто-то сокращает слова - но это уже никакой поиск не найдёт. Также можно повыкидывать из поиска все знаки препинания - и проверять на них уже полученную предварительным поиском номенклатуру. Если пользователь указывает несколько слов, разделённых пробелом - то сначала можно искать каждое слово, а потом по результату выбрать те, где первое идёт перед вторым (если, конечно, пользователю это важно). |
Форум | Правила | Описание | Объявления | Секции | Поиск | Книга знаний | Вики-миста |