Имя: Пароль:
1C
1C 7.7
v7: После перевода базы на SQL время выполнения запроса возросло в 50 раз!
0 Калиостро
 
28.05.13
00:10
Справочник номенклатуры содержит около 25000 элементов.
Количество уровней - 6.
Есть реквизит "Код сортировки", строка, длина 3. Используется для групп и элементов.
Фактически заполняется только для групп с целью отсортировать для вывода прайс-листа и каталога.

СписокНоменклатуры - заполняется элементами с учетом нескольких фильтров и содержит около 5000 элементов
И дальше запрос.

ТекстЗапроса = "
|Обрабатывать НеПомеченныеНаУдаление;
|Номенклатура = Справочник.Номенклатура.ТекущийЭлемент;
|Условие (Номенклатура в СписокНоменклатуры);
|Группировка Номенклатура Упорядочить по Номенклатура.КодСортировки,Номенклатура.Наименование;";    

На базе DBF выполнялся 20 сек.

Теперь, после перевода на SQL, время выполнения запроса около 18 мин!
1 Калиостро
 
28.05.13
00:11
Если делаю прямой запрос

   |select
   |    СпрНоменклатура.ID [Номенклатура $Справочник.Номенклатура]
   |,$СпрНоменклатура.КодСортировки As КодСортировки
   |,РОД1.ID [Родитель1 $Справочник.Номенклатура]
   |,РОД2.ID [Родитель2 $Справочник.Номенклатура]
   |,РОД3.ID [Родитель3 $Справочник.Номенклатура]
   |,РОД4.ID [Родитель4 $Справочник.Номенклатура]
   |,РОД5.ID [Родитель5 $Справочник.Номенклатура]
   |,РОД6.ID [Родитель6 $Справочник.Номенклатура]
   |from
   |    $Справочник.Номенклатура AS СпрНоменклатура
   |LEFT JOIN
   |    $Справочник.Номенклатура РОД1 ON СпрНоменклатура.parentID = РОД1.ID
   |LEFT JOIN
   |    $Справочник.Номенклатура РОД2 ON РОД1.parentID = РОД2.ID
   |LEFT JOIN
   |    $Справочник.Номенклатура РОД3 ON РОД2.parentID = РОД3.ID
   |LEFT JOIN
   |    $Справочник.Номенклатура РОД4 ON РОД3.parentID = РОД4.ID
   |LEFT JOIN
   |    $Справочник.Номенклатура РОД5 ON РОД4.parentID = РОД5.ID
   |LEFT JOIN
   |    $Справочник.Номенклатура РОД6 ON РОД5.parentID = РОД6.ID
   |WHERE
   |    СпрНоменклатура.ID IN (SELECT Val FROM #СписокНоменклатуры)
   |ORDER BY
   |    $СпрНоменклатура.КодСортировки
   |";

То на выходе необходимый список элементов со всеми группами. Но как вытащить ту же структуру групп с сортировкой по полю "КодСортировки", что получается в результате черного запроса?
2 Злопчинский
 
28.05.13
00:17
"КодСортировки" - стоит флажок сортировка" в пофигуртаоре?
3 Калиостро
 
28.05.13
00:25
(2) Нет.
4 Злопчинский
 
28.05.13
00:29
(3) а попробовать поставить?
5 Злопчинский
 
28.05.13
00:31
и не нравится мне
|Условие (Номенклатура в СписокНоменклатуры);
с учетом 25000 раз проверить вхождение в список из 5000 элементов...
6 Злопчинский
 
28.05.13
00:32
для начала тупо закомментируй это условие и проверь.
7 Калиостро
 
28.05.13
00:34
(4), (5) спасибо, завтра буду экспериментировать, отпишусь.
8 Холст
 
28.05.13
01:01
(5) а оно не кешируется разве ?
9 Злопчинский
 
28.05.13
01:01
(8) хз, я не спец. но мну такое не нравится...
10 Холст
 
28.05.13
01:04
(9) а чем ты заменяешь подобное условие ?
11 Злопчинский
 
28.05.13
01:07
(10) ничем, ятакой хренью не занимаюсь, у меня номенклатуры на порядок меньше.. ;-)
.
если это разовый отчет - то и пофиг.
если это регулярный отчет - то в эти 5000 прописать флажок=1 в индексируемое поле и отбирать по этому полю.
.
но я по запросам и их тонкой трактовке - не спец. лучше спецов дождаться.
12 viktor_vv
 
28.05.13
01:56
Можно еще попробовать для штатного черного

Запрос.ВключитьSQL(0) ;
Запрос.Выполнить(ТекстЗапроса);
13 Balabass
 
28.05.13
02:09
(12) +1
14 второй Вах
 
28.05.13
02:36
ни разу не встречал чтоб под скуль сервером быстее чем на дбф работало
15 второй Вах
 
28.05.13
02:45
+ в таких мелких базах, разумеется
16 МихаилМ
 
28.05.13
09:30
в 1с77 sql чтобы это запрос работал быстрее,
нужно отказаться от сортировки. тк для каждого элемента выборки
после получения выборки будет сгенерирован запрос

5000 элементов = + 5000 запросов.

поэтому лучше сортировать тз после выборки и выгрузки


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

конструкцию в лучше заменть  Условие (Номенклатура = пар[1]
ИЛИ ... Номенклатура = пар[N].

есть ограничение на размер текста запроса odbc клиента

так что в одном запросе можно указать не более 2200 9 символьных ключей.
17 пипец
 
28.05.13
09:31
в скуле упорядочивать по текстовому полю типа наименование - да еще вторым номером ...
18 Sorm
 
28.05.13
09:43
(0) "@Условие (Номенклатура в СписокНоменклатуры)" убрать. По возможности заменить джоином с временной таблицей(плохо знаю запросы 1с 7.7). Отребилдить индексы на таблице номенклатуры.
19 МихаилМ
 
28.05.13
09:48
(2)
почему в запросе  нет подсказок "nolock"

лучше элементы выбирать отдельно , группы отдельно (есть индекс для групп)
20 7Hawk7
 
28.05.13
10:31
ВыбратьЭлементы() в 7 для справочников работает быстрее запроса, попробуй выборку.
21 Калиостро
 
28.05.13
10:37
(11) Отчет не разовый, запускается как минимум 1 раз в день по регламенту или по требованию.

Флаг сортировки у реквизита "КодСортировки" поставил.

Команду ВключитьSQL(1) добавил.

Результат практически нулевой.

(19) nolock в запросе поставлю. Запрос в (1) запускался в тестовой базе.

(20) ОК, буду пробовать.
22 viktor_vv
 
28.05.13
10:48
(21) Надо ВключитьSQL(0) .
23 viktor_vv
 
28.05.13
10:49
(22)+ Не факт что поможет, но бывает.
24 МихаилМ
 
28.05.13
11:29
(20) выбрать элементы быстрее работает для dbf варианта
для sql выборка из запросов быстрее
25 7Hawk7
 
28.05.13
11:53
(24) проводил замеры? я да, и результат указал в (20)
26 МихаилМ
 
28.05.13
12:00
(25)
конечно мерил. в 2003 году.

естественно файловая база и ms sql были доступны через сеть 100 mb

локальные замеры - бессмысленны.
27 dk
 
28.05.13
12:13
проверял несколько раз на разных базах скуль
если в списке значений для фильтра больше 100 элементов, то быстрее на клиенте отфильтровать, через
Условие (СписокНоменклатуры.Принадлежит(Номенклатура)=1)
28 ЧеловекДуши
 
28.05.13
12:18
(0) Это нормальное явление, 1С не оптимизирует запросы к SQL, поэтому и тормоза.
Начни осваивать 1С++ и прямые запросы :)
29 ЧеловекДуши
 
28.05.13
12:18
(20) Бред, нет нечего лучше, чем наш Select From $Справочник.Такой-то :)
30 ДенисЧ
 
28.05.13
12:19
(29) Есть... TRUNCATE TABLE $Справочник.Такойто...
31 ЧеловекДуши
 
28.05.13
12:20
(1) >>>    |LEFT JOIN
   |    $Справочник.Номенклатура РОД1 ON СпрНоменклатура.parentID = РОД1.ID
   |LEFT JOIN
   |    $Справочник.Номенклатура РОД2 ON РОД1.parentID = РОД2.ID
   |LEFT JOIN
   |    $Справочник.Номенклатура РОД3 ON РОД2.parentID = РОД3.ID
   |LEFT JOIN
   |    $Справочник.Номенклатура РОД4 ON РОД3.parentID = РОД4.ID
   |LEFT JOIN
   |    $Справочник.Номенклатура РОД5 ON РОД4.parentID = РОД5.ID
   |LEFT JOIN
   |    $Справочник.Номенклатура РОД6 ON РОД5.parentID = РОД6.ID

Убери эту гадость :)
32 ЧеловекДуши
 
28.05.13
12:20
(30) Злодей ;)
33 Злопчинский
 
28.05.13
13:04
ну так что?
34 sapphire
 
28.05.13
13:05
(30) Я тебя заразил? :)
35 sapphire
 
28.05.13
13:06
(0) Версия SQL?
36 Калиостро
 
28.05.13
13:10
(35) 2000
37 Калиостро
 
28.05.13
13:11
Такой запрос
   |Обрабатывать НеПомеченныеНаУдаление;
   |Номенклатура = Справочник.Номенклатура.ТекущийЭлемент;
   |Группировка Номенклатура Упорядочить по Номенклатура.КодСортировки;";  

Без фильтров и без сортировки по наименованию отрабатыаает на локальной машине за 7 сек, на сервере - 15 сек.
38 dk
 
28.05.13
13:15
(37) добавь "без итогов"
39 dk
 
28.05.13
13:18
(38)+ сделай по 2-3 запуска и посмотри как меняется / не меняется время
40 Эмбеддер
 
28.05.13
13:20
а если вместо СпрНоменклатура.ID [Номенклатура $Справочник.Номенклатура]
сделать просто СпрНоменклатура.ID ?
41 Калиостро
 
28.05.13
13:52
+(37) К запросу добавляю
   |Условие (Номенклатура в СписокНоменклатуры);

СписокНоменклатуры содержит 12000 элементов.

На ноутбуке (тоже SQL 2000) запрос выполняется 10 минут.

На сервере не проверял. Все равно долго.
42 Калиостро
 
28.05.13
13:57
(40) У меня не получается прямым запросом вытащить иерархию групп для СписокНоменклатуры, упорядоченную по КодСортировки. Если есть образец, буду премного благодарен.

Поэтому сейчас пытаюсь выйти на приемлемое время с помощью черного запроса.

Пусть не 20 сек, как в DBF, но и не 10 минут же!
43 Злопчинский
 
28.05.13
14:03
мне принципиально кажется что необходимость регулярно проверять условие по вхождение в немелкий список - что-то в концепции попраить надо...?
44 Serginio1
 
28.05.13
14:09
(1) Посмотри http://1c.proclub.ru/modules/mydownloads/personal.php?cid=115&lid=2019 там есть обработка вывода иерархии
добавил обработки по группировке данных и выводе с учетом иерархии и суммам по группам иерархи из ТаблицыЗначений
45 Эмбеддер
 
28.05.13
14:09
(42) и все-таки еще раз - тормоза могут быть уже при чтении результата запроса. попробуй убрать [..$Справочник], считай просто строки
46 dk
 
28.05.13
14:10
(42) попробуй вариант (27)
47 Эстет хренов
 
28.05.13
14:35
дурная работа, уже давно бы сделал справочник Прайс-лист в котором бы настраивал всю специфику каталогов и прайс-листов.
Там можно создать различную иерархию, множественную вложенность товаров, свою сортировку, свое представление и оформление итд итп.
48 Калиостро
 
28.05.13
14:49
(46) И как там получить отсортированный иерархический список групп по списку номенклатуры?
49 Калиостро
 
28.05.13
14:56
(47) Дурная - не дурная, лучше не давать оценок, пока видишь только вершину айсберга проблем. База dbf работала с 2005 года. Чтобы после перевода на SQL запрос по номенклатуре выполнялся в 50 раз медленнее - этого, конечно, не ожидал.
50 Злопчинский
 
28.05.13
15:13
(49) ну и фигли - это не значит, что все хорошо. как правило - смотришь на все это и думаешь, блин, ну что за уродство...
.
не.. когда из 25000 надо отфильтровать по вхождению в 12000 список - это не 5-6 позиций подбираемых руками - это уже какая-то система. а система - это флажки, реквизиты, но ну никак не список на 5000/12000 позиций, однозначно в консерватории...
51 Калиостро
 
28.05.13
15:30
(50) Немного не в тему топика, но раз уж зашел разговор. В номенклатуре есть признак "Включать в прайс" и варианты:
1. Всегда (например, позиции собственного производства).
2. Никогда (специфические позиции раньше торговали массово, а теперь распродажа остатков с прилавка).
3. При остатке больше заданного количества (например, когда через интернет-магазин продавать меньше упаковки невыгодно).

Формировать список, по-моему, здесь можно только в момент выгрузки, анализировать и перезаписывать флажки при проведении документов - еще хуже.
52 Mikeware
 
28.05.13
15:32
(49) ну и у меня работает с 2005. иногда смотришь и думаешь - убил бы того, кто такое написал... а поразмыслишь - ну разве ж это повожд для самоубийства? :-)
53 Калиостро
 
28.05.13
15:33
+ (51) Я и не говорю, что там все идеально. Система дописывалась годами. Где-то были глобальные переделки, где-то костыли. Сейчас тоже надо поставить костыль. Передохнем, а дальше подумаем.
54 Калиостро
 
28.05.13
15:37
(52) + 100. Если бы каждый раз при возникновении новой задачи надо было переделывать архитектуру с нуля, так и занимались бы описанием, согласованием ТЗ, тестированием, отладкой 90% времени. Лучше сейчас решить задачу на тройку. Если критических глюков не будет, когда-нибудь в свободное время  займемся рефакторингом.
55 aka AMIGO
 
28.05.13
15:38
(0) переходи на прямые © запросы :)
у меня примерно такая-же ситуация была, когда надежды шефа на ускорение разрушились: отчет в скуле стал работать в 3 раза медленнее.. всего в 3! а у тебя 50 :)
56 Калиостро
 
28.05.13
15:43
(55) Дайте рыбу списать:(
Надо получить иерархию групп для СписокНоменклатуры, упорядоченную по КодСортировки. Как в черном запросе "
   |Номенклатура = Справочник.Номенклатура.ТекущийЭлемент;
   |Группировка Номенклатура Упорядочить по Номенклатура.КодСортировки;
   |Условие (Номенклатура в СписокНоменклатуры);
57 Sorm
 
28.05.13
15:52
(1)     |LEFT JOIN
       |(Select Val from FROM #СписокНоменклатуры order by Val) Список
       |on Список.ID = СпрНоменклатура.ID

Я не знаю, так можно делать в прямых запросах 7.7.... Но скорость запроса возрастет.
58 Сияющий Асинхраль
 
28.05.13
15:54
(27) А еще быстрее, как ни странно, заменить
Условие (СписокНоменклатуры.Принадлежит(Номенклатура)=1)
На:
Условие (СписокНоменклатуры.НайтиЗначение(Номенклатура)<>0)
Причем, что забавно НайтиЗначение частенько работает быстрее чем Принадлежит буквально в разы...
59 Mikeware
 
28.05.13
15:57
(58) потому, что Найти - ищет в списке, а принадлежит - в иерархии. а поиск в иерархии - это запрос к базе
60 Mikeware
 
28.05.13
15:57
+(59) и он может отличаться не в разы, а на порядок
61 Mikeware
 
28.05.13
15:58
(56) все-таки, я не понял что тебе нужно _в_результате_
62 Сияющий Асинхраль
 
28.05.13
16:01
(60) Согласен... Давно на эту бадягу напоролся, уже несколько лет семеркой занимаюсь от случая к случаю, но разница на опыте оказалась такая существенная, что до сих пор помню, что Принадлежит лучше не использовать :-)))
63 Калиостро
 
28.05.13
16:05
(61)Нужен список групп в определенной последовательности. Внутри одной группы порядок по полю "КодСортировки". Нужны не все группы, а только те, в которые входят элементы из списка.
Вроде бы в запросе (56) это просматривается.
64 Эмбеддер
 
28.05.13
16:05
(57) вообще-то это делается так
LEFT JOIN
#СписокНоменклатуры Список
on Список.ID = СпрНоменклатура.ID

автор, тебя здесь все уговаривают сделай так, сделай так. а ты придумываешь всякие отмазки почему не надо это делать
65 Эмбеддер
 
28.05.13
16:06
64+ потому что в принципе на SQL такие прямые запросы в принципе не могут долго выполняться
66 Эмбеддер
 
28.05.13
16:10
вместо LEFT JOIN просто JOIN - так скопировал
67 Bugmenot
 
28.05.13
16:13
(0) - и после этого вы еще считаете, что архитектура 1С - это Порше?

v8: Переход c Oracle Application на 1С
68 Mikeware
 
28.05.13
16:14
(63) выбери всех прямых родителей элементов списка в индексированную таблицу, и сгруппируй по иерархии.
69 Bugmenot
 
28.05.13
16:15
(0) - это разрыв шаблона, обычно при переходе на SQL все должно убыстряться, т.к. по сети гуляют не таблицы, а запросы.
70 Sorm
 
28.05.13
16:17
(64)+ Буду знать. Ну я его код скопировал.... Идея понятна, конечно - уйти от where.
71 Classic
 
28.05.13
16:21
(69)
СКЛ в принципе зло
72 ДенисЧ
 
28.05.13
16:23
(69) Не в этой жизни. То есть не в 1с
73 Bugmenot
 
28.05.13
16:25
(71) - дело не в SQL, а в том, что фирма 1Це не оптимизиорвала свою т.н. SQL версию для SQL
74 Эмбеддер
 
28.05.13
16:30
(69) все меньше остается 1Сников, которые видели 7-ку, а сама она переходит в разряд мифов
кроме того как автор выводит группировку, будет странный результат - не учитывается, что элементы будут на разных уровнях
75 Калиостро
 
28.05.13
16:30
(68) Нужны не только прямые родители, а вся иерархия от 1 уровня.
76 Mikeware
 
28.05.13
16:32
(75) ты читать умеешь?
77 Mikeware
 
28.05.13
16:32
(74) а "восьмерка разжижает мозг"©
78 ДенисЧ
 
28.05.13
16:33
(77) не всем, не всем....
79 Калиостро
 
28.05.13
16:36
(76) Запрос в (1) дает все нужные группы. Попробую покрутить ИТ.
80 Serginio1
 
28.05.13
16:43
(79) Сделай дерево наподобие в 44 и будет тебе счастье.
Или Сделай на индексированной таблице с отбором по родителю
81 Калиостро
 
28.05.13
17:06
(64)
   ТекстЗапроса = "
   |SELECT
   |    СпрНоменклатура.ID [Номенклатура $Справочник.Номенклатура]
   |FROM
   |  $Справочник.Номенклатура as СпрНоменклатура (NOLOCK)
   |LEFT JOIN
   |    #СписокНоменклатуры Список on Список.ID = СпрНоменклатура.ID
   |";
   Запрос = СоздатьОбъект("ODBCRecordSet");
   Запрос.Отладка(1);
   Запрос.УложитьСписокОбъектов(СписокНоменклатуры, "#СписокНоменклатуры", "Номенклатура");
   ТЗ = Запрос.ВыполнитьИнструкцию(ТекстЗапроса);  

Error: State 42S22, native 207, message [Microsoft][ODBC SQL Server Driver][SQL Server]Invalid column name 'ID'.
82 ДенисЧ
 
28.05.13
17:07
Список.ID

а документацию кто читать будет?
83 viktor_vv
 
28.05.13
17:07
#СписокНоменклатуры Список on Список.VAL = СпрНоменклатура.ID
84 Калиостро
 
28.05.13
17:40
Пойдем путем банана...

   |SELECT
   |    СпрНоменклатура.ID [Номенклатура $Справочник.Номенклатура]
   |FROM
   |  $Справочник.Номенклатура as СпрНоменклатура (NOLOCK)
   |JOIN
   |    #СписокНоменклатуры Список on Список.Val = СпрНоменклатура.ID
   |";
   Запрос = СоздатьОбъект("ODBCRecordSet");
   Запрос.УложитьСписокОбъектов(СписокНоменклатуры, "#СписокНоменклатуры", "Номенклатура");

Выдает список номенклатуры из СписокНоменклатуры. Групп нет. Печаль.
85 Mikeware
 
28.05.13
17:43
(84) сочувствую.
parentId, а затем (68)
86 Mikeware
 
28.05.13
17:43
кстати, distinct еще...
87 Ёпрст
 
гуру
28.05.13
17:49
(0) скуль какой хоть ?
88 Ёпрст
 
гуру
28.05.13
17:51
вот, один из способов показа всей иерархии (но, для скуля>=2005)
http://www.1cpp.ru/forum/YaBB.pl?num=1367434674
89 NS
 
28.05.13
18:03
(0) Есть очень быстрый способ штатного получения всех групп... Отсортировать можно уже в ТЗ.
90 NS
 
28.05.13
18:05
А понял, тебе не группы нужно.
91 Калиостро
 
28.05.13
18:09
(89) Элементы у меня уже есть. Мне нужны как раз группы. Но не все и в определенном порядке.
92 Калиостро
 
28.05.13
18:09
(87) 2000
93 NS
 
28.05.13
18:10
(91) А что, отсортировать их после получения нельзя?
Или у тебя их миллион?
94 Serginio1
 
28.05.13
18:15
(93) Ему нужна иерархия. Ему уже указали как решить проблему
Через индексированную таблицу с рекурсивным отбором по родителю, либо через построение дерева 44.
95 fisher
 
28.05.13
18:31
(0) А без упорядочивания сабжевый запрос сколько выполняется?
96 Serginio1
 
28.05.13
18:34
То что Ёпрст предложил в 88 Получаешь таблицу

А дальше рекурсивно
Установить Индекс
Тз.ДобавитьИндекс("РодительИндех", "Родитель");


Процедура ВывестиУровень(Родитель)
перем ТзРодителей;
Тз.УстановитьФильтр(Родитель, Родитель, "РодительИндех");


Тз.Выгрузить(ТзРодителей);

ТзРодителей.Сортировать("IsFolder,КодСортировки");

ТзРодителей.ВыбратьСтроки();
Пока ТзРодителей.ПолучитьСтроку()=1 Цикл
//Вывести текущий элемент
Если ТзРодителей.IsFolder=1 Тогда
ВывестиУровень(Тз.Номенклатура)

КонецЕсли;
КонецЦикла;
КонецПроцедуры
Кaк может человек ожидaть, что его мольбaм о снисхождении ответит тот, кто превыше, когдa сaм он откaзывaет в милосердии тем, кто ниже его? Петр Трубецкой