Имя: Пароль:
1C
1С v8
Почему не работает быстрее запросом
0 sidalexsandr
 
20.12.12
11:40
Вчера написал поиск двух подчиненных документов
(подчиненность определял на основании реквизита шапки ДокОснование).
Выполняется поиск подчинённых документов при открытии документа - основания.
Решил задачу двумя способами (Документ основание Ведомость, подчиненные
документы СписаниеТоваров и ПеремещениеТоваров):

1) Запросом:
Функция ВернутьЕстьПеремещениеЕстьСписание()

   Запрос = Новый Запрос;
   Запрос.Текст = "
|ВЫБРАТЬ  
|ВЫБОР  
|
|    КОГДА Количество(*) > 0 ТОГДА ""1""  
|
|    
|    ИНАЧЕ ""0""  
|
| КОНЕЦ ЕстьПодчиненнныеДокум  
|ИЗ
|(ВЫБРАТЬ
|    СписаниеТоваров.Ссылка КАК Перемещение,    
|    СписаниеТоваров.ДокОснование.Ссылка КАК ОснованиеПеремещение
|ИЗ
|    Документ.СписаниеТоваров КАК СписаниеТоваров
|ГДЕ
|    СписаниеТоваров.ДокОснование.Ссылка = &ТекВедомость) КАК Вложенный
|
|ОБЪЕДИНИТЬ ВСЕ
|
|ВЫБРАТЬ  
|ВЫБОР
|
|    КОГДА Количество(*) > 0 ТОГДА ""1""  
|
|    
|    ИНАЧЕ ""0""  
|
| КОНЕЦ ЕстьПодчиненнныеДокум  
|ИЗ
|(ВЫБРАТЬ
|    ПеремещениеТоваров.Ссылка КАК Перемещение,    
|    ПеремещениеТоваров.ДокОснование.Ссылка КАК ОснованиеПеремещение
|ИЗ
|    Документ.ПеремещениеТоваров КАК ПеремещениеТоваров
|ГДЕ
|    ПеремещениеТоваров.ДокОснование.Ссылка = &ТекВедомость) КАК Вложенный";
Запрос.УстановитьПараметр("ТекВедомость", ЭтотОбъект.Ссылка);
РезультатЗапроса = Запрос.Выполнить();    

   Если Запрос.Выполнить().Пустой() = Истина Тогда
       Возврат "Нет подчиненных документов";  
   Иначе
       // В запросе есть документы Ведомость
       РезультатЗапроса = Запрос.Выполнить().Выбрать();
       Возврат РезультатЗапроса;
   КонецЕсли;


КонецФункции // ВернутьЕстьПеремещениеЕстьСписание()

2) Циклом с помощью перебора:
Процедура ЕстьПеремещениеЕстьСписание(ЕстьСписание, ЕстьПеремещение)
   
   ЕстьСписание = 0;
   ЕстьПеремещение = 0;
   Списание = Документы.СписаниеТоваров.Выбрать();
   Пока Списание.Следующий() Цикл    
       Если ЗначениеЗаполнено(Списание.ДокОснование) = Ложь Тогда
           Продолжить;    
       КонецЕсли;    
       Если Списание.ДокОснование.Ссылка = ЭтотОбъект.Ссылка Тогда    
           ЕстьСписание = 1;                                              
       КонецЕсли;                                                    
   КонецЦикла;    
   
   Перемещение = Документы.ПеремещениеТоваров.Выбрать();
   Пока Перемещение.Следующий() Цикл    
       Если ЗначениеЗаполнено(Списание.ДокОснование) = Ложь Тогда
           Продолжить;    
       КонецЕсли;      
       Если Перемещение.ДокОснование.Ссылка = ЭтотОбъект.Ссылка Тогда
            ЕстьПеремещение = 1;
       КонецЕсли;                                                    
   КонецЦикла;    
   
КонецПроцедуры // ЕстьПеремещениеЕстьСписание(ЕстьСписание, ЕстьПеремещение)

Результат: Процедура написанная запросом в несколько раз медленнее работает, чем процедура
в которой используется перебор документов в цикле.

Вопрос: Почему запросом намного медленнее?
1 sidalexsandr
 
20.12.12
11:42
Задам ещё один вопрос: Когда запросы быстрее работают, а когда лучше писать не используя запросы.
2 Азат
 
20.12.12
11:43
а критерий отбора тут не поможет? какой-то запрос эббонутый, если честно
3 GLazNik
 
20.12.12
11:43
Ну запрос какашка. А за такое "СписаниеТоваров.ДокОснование.Ссылка" вообще в монастырь отправлять надо...
4 Starhan
 
20.12.12
11:43
(0)

РезультатЗапроса = Запрос.Выполнить();    

   Если Запрос.Выполнить().Пустой() = Истина Тогда
       Возврат "Нет подчиненных документов";  
   Иначе
       // В запросе есть документы Ведомость

       РезультатЗапроса = Запрос.Выполнить().Выбрать();
       Возврат РезультатЗапроса;
   КонецЕсли;

ничо что ты три раза запрос выполняешь?
5 Undefined vs NULL
 
20.12.12
11:43
лучше ответь на вопрос, зачем там подзапросы и зачем писать
СписаниеТоваров.ДокОснование.Ссылка = &ТекВедомость
вместо
СписаниеТоваров.ДокОснование = &ТекВедомость
6 Starhan
 
20.12.12
11:44
не все таки самый смак это три раза выполнить дин и тот де запрос :)
7 GLazNik
 
20.12.12
11:44
(4) :)
8 Undefined vs NULL
 
20.12.12
11:44
кстати условие Если Запрос.Выполнить().Пустой() = Истина Тогда
вообще не может выполниться с данным запросом
9 cw014
 
20.12.12
11:45
Ужас.... [убежал пить валерьянку]
10 del123
 
20.12.12
11:46
(4) ахахах))
11 Deon
 
20.12.12
11:47
(4) Хе, спасибо, поржал )
12 sidalexsandr
 
20.12.12
11:48
(5) Спасибо за критику, учту.
13 cw014
 
20.12.12
11:49
У тебя три непростительные ошибки (тебе впрочем их все перечислили, но я подытожу):
1) Вложенные таблицы в запросе - вот в нем вообще не нужны
2) ПеремещениеТоваров.ДокОснование.Ссылка = &ТекВедомость - по ссылке еще и ссылку тягаешь (дополнительную таблицу) - вообще за такое расстрелять надо
3) в (4) внятно показали - накуя три раза запрос выполнять? Нет, ну можно и 15 раз, еще медленнее будет, потом на запросы грязь лить...

В общем - включи моск
14 Undefined vs NULL
 
20.12.12
11:49
запросы 1С настолько плохи, что их надо вызывать не менее 3 раз
15 del123
 
20.12.12
11:49
(12) ты лучше (4) учти)
16 sidalexsandr
 
20.12.12
11:49
(4) Спасибо.
17 sidalexsandr
 
20.12.12
11:50
(2) Подумаю.
18 pessok
 
20.12.12
11:52
(17) правильный ответ в (2)
19 hhhh
 
20.12.12
11:53
(14) а разве результат запроса не сохраняется в кеше?
20 Jstunner
 
20.12.12
11:53
Похоже, у нас есть победитель в самой престижной номинации года..
21 Азат
 
20.12.12
11:55
(14) если ты съешь 3 какашки, то это равносильно одной шоколадке?
22 Jstunner
 
20.12.12
11:56
(19) это получилось бы ахинея какая-то..
23 Undefined vs NULL
 
20.12.12
11:56
(19) во-первых в кеше чего?
во-вторых он может там сохраняться, но не обязан
24 sidalexsandr
 
20.12.12
11:57
(4) Так правильно:
Запрос = Новый Запрос;
Запрос.Текст = "
|ВЫБРАТЬ  
|ВЫБОР
|
|    КОГДА Количество(*) > 0 ТОГДА ""1""  
|
|    
|    ИНАЧЕ ""0""  
|
| КОНЕЦ ЕстьПодчиненнныеДокум  
|ИЗ
|(ВЫБРАТЬ
|    ПеремещениеТоваров.Ссылка КАК Перемещение,    
|    ПеремещениеТоваров.ДокОснование КАК ОснованиеПеремещение
|ИЗ
|    Документ.ПеремещениеТоваров КАК ПеремещениеТоваров
|ГДЕ
|    ПеремещениеТоваров.ДокОснование = &ТекВедомость) КАК Вложенный
|    
|ОБЪЕДИНИТЬ ВСЕ
|
|ВЫБРАТЬ  
|ВЫБОР  
|
|    КОГДА Количество(*) > 0 ТОГДА ""1""  
|
|    
|    ИНАЧЕ ""0""  
|
| КОНЕЦ ЕстьПодчиненнныеДокум  
|ИЗ
|(ВЫБРАТЬ
|    СписаниеТоваров.Ссылка КАК Перемещение,    
|    СписаниеТоваров.ДокОснование КАК ОснованиеПеремещение
|ИЗ
|    Документ.СписаниеТоваров КАК СписаниеТоваров
|ГДЕ
|    СписаниеТоваров.ДокОснование = &ТекВедомость) КАК Вложенный";
Запрос.УстановитьПараметр("ТекВедомость", ЭтотОбъект.Ссылка);

РезультатЗапроса = Запрос.Выполнить().Выбрать();
25 Азат
 
20.12.12
11:57
(19) аха, манагеры проводят реализации, а дирик перед зарплатой посмотрел отчет из кэша, что они ниче не продали и выплатил им по 2000 :D :D :D
26 Undefined vs NULL
 
20.12.12
11:59
(24) убери подзапросы, будь мужиком
27 Undefined vs NULL
 
20.12.12
12:00
(0) что ты делал 7 лет?
28 Азат
 
20.12.12
12:01
(24) а если примерно так?

"ВЫБРАТЬ
|    СвязанныеДокументы.Ссылка
|ИЗ
|    КритерийОтбора.СвязанныеДокументы(&Ссылка) КАК СвязанныеДокументы
|ГДЕ
|    СвязанныеДокументы.Ссылка ССЫЛКА Документ.СписаниеТМЦ
|ИЛИ СвязанныеДокументы.Ссылка ССЫЛКА Документ.ПеремещениеТМЦ"
29 Азат
 
20.12.12
12:01
а потом посмотри: Если Выборка.Следующий() Тогда ЕПРСТ!!! ЗНАЧИТ, ЕСТЬ!!! КонецЕсли;
30 sidalexsandr
 
20.12.12
12:02
(4) Так правильно:
Запрос = Новый Запрос;
Запрос.Текст = "
|ВЫБРАТЬ  
|ВЫБОР
|
|    КОГДА Количество(*) > 0 ТОГДА ""1""  
|
|    
|    ИНАЧЕ ""0""  
|
| КОНЕЦ ЕстьПодчиненнныеДокум  
|ИЗ
|(ВЫБРАТЬ
|    ПеремещениеТоваров.Ссылка КАК Перемещение,    
|    ПеремещениеТоваров.ДокОснование КАК ОснованиеПеремещение
|ИЗ
|    Документ.ПеремещениеТоваров КАК ПеремещениеТоваров
|ГДЕ
|    ПеремещениеТоваров.ДокОснование = &ТекВедомость) КАК Вложенный
|    
|ОБЪЕДИНИТЬ ВСЕ
|
|ВЫБРАТЬ  
|ВЫБОР  
|
|    КОГДА Количество(*) > 0 ТОГДА ""1""  
|
|    
|    ИНАЧЕ ""0""  
|
| КОНЕЦ ЕстьПодчиненнныеДокум  
|ИЗ
|(ВЫБРАТЬ
|    СписаниеТоваров.Ссылка КАК Перемещение,    
|    СписаниеТоваров.ДокОснование КАК ОснованиеПеремещение
|ИЗ
|    Документ.СписаниеТоваров КАК СписаниеТоваров
|ГДЕ
|    СписаниеТоваров.ДокОснование = &ТекВедомость) КАК Вложенный";
31 sidalexsandr
 
20.12.12
12:03
(28) Сейчас проверю.
32 cw014
 
20.12.12
12:04
(30) Убери подзапросы, япона мать
33 sidalexsandr
 
20.12.12
12:05
(29) СписаниеТМЦ - это вроде из 7.7, а в 1с 8.2 СписаниеТоваров.
34 Александр Б
 
20.12.12
12:06
(0) гуанокод детектед
35 Азат
 
20.12.12
12:06
(33) в моей самописке оно называется Списание ТМЦ... ты уж подсуетись, переименуй, как тебе надо... или ты все же 1986 гр?
36 Lys
 
20.12.12
12:07
(30) самое правильное - это вот так:
http://bit.ly/VT27R4
37 sidalexsandr
 
20.12.12
12:15
(35) Да я переименовал, спасибо за помощь. Просто удивился, что 8.2 СписаниеТМЦ.
38 sidalexsandr
 
20.12.12
12:16
(36) Не засоряй. Я учусь и исправляю, то что советуют.
39 sidalexsandr
 
20.12.12
12:19
(35) Спасибо огромное. Благодаря тебе освоил критерии отбора.
40 sidalexsandr
 
20.12.12
12:44
(32) Поделись пожалуйста откуда так хорошо освоил написание запросов. Я тоже хочу почитать и разобраться.
41 Азат
 
20.12.12
12:44
(40) попади на проект, где база гигов 30-40... мигом научишься запросы оптимизировать :D :D

(39) не за что...
42 sidalexsandr
 
20.12.12
12:47
(41) Тогда надо попросить у кого-нибудь базу объемом 30-40 Гигов. Кстати и вчера думал у кого-нибудь УПП попросить с большим объемом данных, а то у самого чистая (только несколько документов для теста).
43 Fragster
 
гуру
20.12.12
12:47
"Выбрать первые 1" еще можно
44 Fragster
 
гуру
20.12.12
12:47
у меня файловые 20-30 гигов, и в них по 5-10 юзеров работают... вот там оптимизировать - это да, забавно
45 sidalexsandr
 
20.12.12
12:48
(44) УПП?
46 ptiz
 
20.12.12
12:49
(42) Может и ключи от квартиры? :)
Нагенери сам. Заодно попрактикуешься.
47 Fragster
 
гуру
20.12.12
12:49
(45) адская, действительно адская самописька
48 sidalexsandr
 
20.12.12
12:49
(46) Если не кто не поделетиться, то придется
49 kiruha
 
20.12.12
12:50
(0)
Сколько всего списаний ?
Сколько перемещений ?
Файловая или SQL ?
(файловая при переборе просто движется по файлу)
50 sidalexsandr
 
20.12.12
12:51
(49) Пока пишу, в базе только несколько тестовых документов. Когда запустим в работу, то будет SQL.
51 sidalexsandr
 
20.12.12
12:53
Запрос:
ВЫБРАТЬ
   СвязанныеДокументы.Ссылка
ИЗ
   КритерийОтбора.СвязанныеДокументы(&ТекВедомость) КАК СвязанныеДокументы
ГДЕ
   (СвязанныеДокументы.Ссылка ССЫЛКА Документ.СписаниеТоваров
           ИЛИ СвязанныеДокументы.Ссылка ССЫЛКА Документ.ПеремещениеТоваров)

Вернул:
Ссылка
Перемещение товаров 00000000004 от 13.11.2012 12:10:13
Перемещение товаров 00000000006 от 05.12.2012 9:42:17
Перемещение товаров 00000000005 от 04.12.2012 17:46:22
Списание товаров 00000000006 от 05.12.2012 11:34:33

Вопрос: Подскажите как теперь в запросе. Подсчитать, что:
1. ПеремещениеТоваров > 0 Тогда ЕстьПеремещение = 1
2. СписаниеТоваров > 0 Тогда ЕстьСписание = 1
52 kiruha
 
20.12.12
12:54
Индексировать стоит на ДокОснование - если нет сервер будет в цикле проверять
53 cw014
 
20.12.12
12:55
(51) Различные колонки сделай
54 kiruha
 
20.12.12
12:56
(50)
В чем тогда вопрос - почему сканирование 5 документов быстрее запроса ?

Сделай 10 000 и время увеличится в 2000 раз
55 sidalexsandr
 
20.12.12
12:57
(52) Поставить "Индексирование" у реквизита ДокОснование?
Подскажи пожалуйста ещё поставить просто "Индексирование" или "Индексировать с доп. упорядочиванием"?
56 kiruha
 
20.12.12
12:58
(55)
для запроса пофиг
57 ERWINS
 
20.12.12
12:59
2) ПеремещениеТоваров.ДокОснование.Ссылка = &ТекВедомость - по ссылке еще и ссылку тягаешь (дополнительную таблицу) - вообще за такое расстрелять надо

кто нить проверял есть ли разница? или теоретики?
58 cw014
 
20.12.12
13:03
(57) Ага, есть. Либо ты выбираешь поля _Fld1234RRRef и _Fld1234RTRef и сравниваешь его с ГУИД, либо ты по этим полям делаешь LEFT JOIN _Document1234 по _RRef и в условии ставишь _RRef = ГУИД

(Простите за имена полей и таблиц, уже не помню как они точно именуются)
59 sidalexsandr
 
20.12.12
13:04
(56) Ясно. А для чего тогда "Индексирование"?
60 kiruha
 
20.12.12
13:09
индекс по полю
иногда есть несколько элементов с совпадающим полем
тогда применяют "дополнительное упорядочивание" -
т.е. индекс по 2 полям Поле и его представление - применяется для отображения в списках
61 kiruha
 
20.12.12
13:11
Чтобы индексы где попало не вешать - делают критерий отбора
СвязанныеДокументы в УТ и оттуда уже тянут подчиненные
62 sidalexsandr
 
20.12.12
13:14
(60) Спасибо.
63 НЕА123
 
20.12.12
13:16
чо-то (43) игнорируют.
64 sidalexsandr
 
20.12.12
13:18
(43), (63) Не понял про что
65 cw014
 
20.12.12
13:24
А тема забавна названа, чисто в духе "1С"ника - "Почему не работает быстрее запросом".

Если Не РаботаетБыстрееЗапросом тогда
  Почему();
КонецЕсли;

А по русски хотя бы так обозвал - "Почему запросом работает медленнее...?"
66 Азат
 
20.12.12
13:24
(63) у него не взлетит... ему вообще походу надо просто так сделать:

ВЫБРАТЬ
   МАКСИМУМ(ВЫБОР КОГДА СвязанныеДокументы.Ссылка ССЫЛКА Документ.СписаниеТоваров
       ТОГДА 1
       ИНАЧЕ 0
   КОНЕЦ) КАК Списание,
   МАКСИМУМ(ВЫБОР КОГДА СвязанныеДокументы.Ссылка ССЫЛКА Документ.ПеремещениеТоваров
       ТОГДА 1
       ИНАЧЕ 0
   КОНЕЦ) КАК Перемещение
ИЗ
   КритерийОтбора.СвязанныеДокументы(&ТекВедомость) КАК СвязанныеДокументы
ГДЕ
  (СвязанныеДокументы.Ссылка ССЫЛКА Документ.СписаниеТоваров
          ИЛИ СвязанныеДокументы.Ссылка ССЫЛКА Документ.ПеремещениеТоваров)
67 ERWINS
 
20.12.12
13:26
(58) я делал в 8.1, там было одна и та же скорость
68 sidalexsandr
 
20.12.12
13:31
(66) Спасибо, ты прямо мои мысли прочитал.
69 sidalexsandr
 
20.12.12
13:33
(49) СписанийТоваров ориентировочно будет 5500/год.
70 Fragster
 
гуру
20.12.12
15:23
(66) максимум - это будет хуже, чем первые 1, объединить и свернуть (если в одну строку выборки хочется получить)
71 wertyu
 
20.12.12
15:28
нафиг эти количества и максимум? просто выбрать первые 1