Имя: Пароль:
1C
1С v8
Как ускорить выполнение запроса?
0 vex2865
 
08.01.15
00:51
Есть следующая проблема:

- есть Таблица №1, в ней допустим 50 000 строк, 1 колонка Наименование

- есть Таблица №2, в ней допустим 50 000 строк, 1 колонка Артикул

так вот мне нужно выбрать только те строки где Артикул входит в Наименование.

Запрос у меня следующего вида:

ВЫБРАТЬ
ВременнаяДанныеПоиска.Поле_Наименование_Подготовленное
ПОМЕСТИТЬ ВременнаяДанныеПоиска
ИЗ
&ДанныеПоиска КАК ВременнаяДанныеПоиска
;

////////////////////////////////////////////////////////////////////////////////

ВЫБРАТЬ
ТаблицаАртикулов.АртикулПодготовленный
ПОМЕСТИТЬ ВТАртикулов
ИЗ
&ТЗАртикулов КАК ТаблицаАртикулов
;

////////////////////////////////////////////////////////////////////////////////

ВЫБРАТЬ
ВременнаяДанныеПоиска.Поле_Наименование_Подготовленное,
ВТАртикулов.АртикулПодготовленный
ИЗ
ВременнаяДанныеПоиска КАК ВременнаяДанныеПоиска,
ВТАртикулов КАК ВТАртикулов
ГДЕ
ВременнаяДанныеПоиска.Поле_Наименование_Подготовленное ПОДОБНО "%" + ВТАртикулов.АртикулПодготовленный + "%"


Так вот, тестировал на данных где в Таблице №1 было ~3500 строк, а в Таблице №2 было ~38000 строк - запрос выполняется ~10 мин.

Есть ли какие-то варианты ускорить данный процесс?
1 Asmody
 
08.01.15
00:52
Скакать надо
2 hhhh
 
08.01.15
01:14
(0) вы не то подготовили. Подготовьте наименования, чтобы без ПОДОБНО.
3 vex2865
 
08.01.15
01:26
(2) Не совсем понял, что нужно подготовить...

На сколько я знаю чтобы в запросе проверить вхождение одного текста в другой используется конструкция ПОДОБНО..
4 Asirius
 
08.01.15
02:11
В общем случае, когда Поле_Наименование_Подготовленное имеет неограниченную длину, может вернуться таблица MxN (все артикулы входят во все наименования), а значит полного перебора не избежать.
В случае, когда Поле_Наименование_Подготовленное имеет длину, скажем в 100 символов, а артикул длину ровно 6 символов, можно нарезать временнаяДанныеПоиска.Поле_Наименование_Подготовленное на 100 строк по 6 символов, проиндексировать и искать уже в ней.
Если артикулы имеют разную длину, то можно либо в несколько проходов для каждой длины, либо резать уже сами артикулы
5 senior
 
08.01.15
02:14
Самый лучший вариант это когда при соединении таблиц будет использоваться индекс, но даже если вы его добавите то использоваться он будет только если конструкция подобно будет искать по началу строки, типа а подобно "b%", но не а подобно "%b%"
6 vex2865
 
08.01.15
02:50
(5) Вариант - а подобно "b%" не подойдет. т.к. возмножна ситуация где Артикул будет в середине Наименования...
7 Ник080808
 
08.01.15
02:57
(0) а не быстрее будет уже перебрать сами таблицы на сервере 1с чем пихать их в скуль и там соединять?
8 senior
 
08.01.15
03:27
(6) ну тогда серверу придется при соединении каждой строки просматриватьпросматривать всю таблицу, не могу ничего предложить
(7) может он их дальше в скуле еще использует, а если нет, то это косяк и за это по рукам.
9 Ник080808
 
08.01.15
03:37
(8) так даже если использует в запросе. то только те позиции в которых был артикул. Не проще тогда перебрать на сервере таблицу, получить результат, а потом его уже в запрос пихать
10 Rie
 
08.01.15
03:51
Кажется мне, что вопрос не в том, как ускорить именно запрос из (0). Есть какая-то конкретная задача. И возможны оптимизации, исходя из этой задачи.
Например, в одном "наименовании" не может встречаться два "артикула", а один "артикул" не может принадлежать двум наименованиям и т.п.
11 mdocs
 
08.01.15
04:22
(0) лучший вармант все-таки выделить артикул в отдельную колонку в тз наименования и с ним обработать в запросах. без этого вряд ли чего оптимизируешь.
12 MSOliver
 
08.01.15
04:51
(0) юзать полотекстовый поиск
13 vex2865
 
08.01.15
11:05
(9) Не совсем понятно, что имеется ввиду "перебрать на сервере таблицу"..

(11) Наименование - это динамические данные, каждый раз наименование разное и выделить Артикул в Наименовании не получится.
14 Gantoha
 
08.01.15
11:10
а как вы дожили до того что у вас наименование стало динамическим ?
15 vex2865
 
08.01.15
11:33
(14) Это Наименование поставщика, в каждом прайсе - Наименование товара свое...
16 Бертыш
 
08.01.15
11:55
(13) Скажу Вам к "Наименование - это динамические данные, каждый раз наименование разное и выделить Артикул в Наименовании не получится." разруха у Вас в головах. Запрос тут не поможет.
17 SeraFim
 
08.01.15
12:08
Возможно, запрос из (0) можно чуток ускорить если использовать СОЕДИНЕНИЕ вместо условия.
Сейчас получается декартово произведение - к каждой строчке из таблицы1 присоединяется каждая строка из таблицы2 и только потом полученная таблица отфильтровывается по условию.
Если прописать условие в соединении, то, на мой взгляд, должно получиться чуток быстрее. То есть нужные записи будут фильтроваться уже при соединении
18 Ник080808
 
08.01.15
12:36
(13) Построчный перебор строк таблицы и через найти()
19 vex2865
 
08.01.15
13:10
(17) через СОЕДИНЕНИЕ время выполнения запроса примерно такое же...

(12) Сейчас пытаюсь реализовать данный механизм, надеюсь будет быстрее..
20 DS
 
08.01.15
13:12
(17) В (0) и есть соединение.
21 RomanYS
 
08.01.15
14:23
(20) по условию Истина? независимо от эффективности в (17) правильное замечание
22 vi0
 
08.01.15
15:02
(21) не по условию Истина, а по условию которое в ГДЕ
если делать соединение то план запросов такой же будет
23 TormozIT
 
гуру
08.01.15
16:12
Вполне вероятно, что здесь допустимо
1. с помощью регулярных выражений выделить из каждого наименования все возможные артикулы и получить таблицу (Номенклатура, Наименование, ВозможныйАртикул)
2. соединять по равенству ВозможныйАртикул и Артикул
24 mdocs
 
08.01.15
16:54
Как вариант обойтись без запроса, возможно будет быстрее. Формируем в одну строку с разделителями все наименования и добавляем через спецсимвол номер строки.
Обходим в цикле список артикулов и ищем по нашей большой строке - если значение нашлось - определяем номер строки в которой нашелся артикул (ищем ближайший спецсимвол и парсим номер за ним). Ну как-то так. Фантазия на заданную тему.
25 vex2865
 
08.01.15
17:18
(12) (18) Эти варианты занимают еще больше времени (с данными где в Таблице №1 было ~3500 строк, а в Таблице №2 было ~38000 строк).

(24) Сейчас попробую так)
26 mrDSide
 
08.01.15
17:49
Из обеих таблиц сделать "ВЫБРАТЬ РАЗЛИЧНЫЕ", далее проиндексировать обе по возр/убыв (потесрировать), потом в итоговой выборке делать внутренее соединение.
П.С. вообще лучше без временных таблиц. Зачем они вообще?
27 vex2865
 
08.01.15
18:19
(26) &ДанныеПоиска и &ТЗАртикулов это ТаблицыЗначеий которые я передаю в запрос. Перед передачей их в запрос форматирую Наименование и Артикул по определенному алгоритму (удаление не значащих символов...), а когда в запрос пихаешь ТаблицуЗначений нужно помещать во временную.
28 vex2865
 
09.01.15
11:24
(24) Реализовал таким способом.

- с данными где в Таблице №1 было ~3500 строк, а в Таблице №2 было ~38000 строк - время выполнения ~2-3 мин

- с данными где в Таблице №1 было ~44000 строк, а в Таблице №2 было ~38000 строк - время выполнения ~30 мин
29 exwill
 
09.01.15
11:31
(0) Для того, чтобы кардинально ускорить контекстный поиск нужен специальный индекс. По-другому никак.
30 exwill
 
09.01.15
11:35
+(29) Из штатных механизмов 1С тебе может помочь только менеджер полнотекстового поиска.
31 vex2865
 
09.01.15
11:53
(30) Реализовывал данный механизм, но к сожалению прироста в скорости обработки не было. Самый быстрый вариант на данный момент это (24)
32 exwill
 
09.01.15
11:56
(31) Тогда строй свой индекс. Это будет разновидность (24).
Только - не одна большая строка, а таблица.
33 vex2865
 
09.01.15
12:16
(32) Спасибо, попробую.
34 vex2865
 
09.01.15
12:35
(32) Если я правильно понял:
- в Таблице 1 строю индекс по полю Поле_Наименование_Подготовленное

- далее в цикле по Таблице 2 нужно искать вхождение Артикула в Таблице 1 по Колонке Поле_Наименование_Подготовленное

возникает вопрос.. как искать вхождение Артикула в строку Поле_Наименование_Подготовленное? Метод ТЗ.Найти() ищет по равенству.
35 vi0
 
09.01.15
15:06
(34) если речь про индексы в таблицах значений, то прироста ты можешь не увидеть даже если искать по равенству
доп время займет сама индексация, и выхлоп если будет то в мизерный
попробуй смоделируй на больших таблицах с сотнями или милионами строк