Имя: Пароль:
1C
1C 7.7
v7: Странное поведение прямого запроса
0 DCKiller
 
14.07.11
07:41
Итак, есть прямой запрос, а есть его "кривой" (штатный одинэсовский) аналог. Перечень выбираемых данных у обоих один и тот же, период, фильтры заданы тоже одинаковые. Сначала было так: прямой запрос выполнялся за 9 сек., "кривой" - за минуту с небольшим. Но вдруг что-то стукнуло, и теперь кривой запрос стал выполняться быстрее прямого. Причем время выполнения каждый раз отличается: запрос 1С выполняется то за ту же минуту с маленьким, то за 3 с лишним минуты; прямой же запрос может выполняться в этом случае за 3-4, а порой и за 7 минут! Но всякий раз время выполнения прямого запроса больше времени выполнения "кривого". Новые данные за период не добавлялись совершенно точно, условия выборки не менялись, сервер больше никто не грузит. Что это может быть?
1 1Сергей
 
14.07.11
07:55
ошибка в пятой строке
2 DCKiller
 
14.07.11
07:56
Вот сейчас еще раз выполнил. Результат прямого запроса - 20 сек., запроса 1с - 31 сек. М-да...
3 DCKiller
 
14.07.11
07:56
(1) А?
4 Chum
 
14.07.11
07:57
nolock?
5 ЧеловекДуши
 
14.07.11
07:57
(0)Код в студию :)
6 1Сергей
 
14.07.11
07:57
(3) телепаты в отпуске
7 ЧеловекДуши
 
14.07.11
07:58
Код запроса :)
8 viktor_vv
 
14.07.11
07:58
Если скульная база, обновить статистику и реиндексировать не мешало бы.
9 ЧеловекДуши
 
14.07.11
07:58
(6)Не, не все, в (4) телепатирует :)
Но это все смахивает на гадание :)
10 DCKiller
 
14.07.11
08:00
(7) Какая разница, какой у запроса код? Если он раньше выполнялся быстро, а теперь стал медленно. Код запроса, уверяю вас, тоже не менялся.
11 viktor_vv
 
14.07.11
08:01
Потелепатирую тоже. Если есть соединения замороченных подзапросов лучше переписать через временные таблицы.
12 viktor_vv
 
14.07.11
08:02
Он может каждый раз разные планы запросов было. У меня такое было для (11).
13 Mikeware
 
14.07.11
08:03
(12) а план запросов основывается на статистике..
14 DCKiller
 
14.07.11
08:07
(11) К временным таблицам обращение быстрее?
(13) т.е. каждый раз перед выполнением моего запроса следует обновлять статистику?
15 Mikeware
 
14.07.11
08:09
(14) перед выполнением твоего запроса над ним следует подумать :-)
зы. может, "ошибка там же, где и всегда"? :-))
16 viktor_vv
 
14.07.11
08:11
(14) Скулю проще строить план запоса, вернее более однозначно. Но это зависит от запроса, которого мы так и не увидели.
17 DCKiller
 
14.07.11
08:12
(15) Заменить соединения с таблицами БД на соединения с ВТ? Что еще?
18 Mikeware
 
14.07.11
08:13
(17) ДНК поправить...
19 DCKiller
 
14.07.11
08:14
(16) Ладно, держи...

SELECT
   ПродажиОбороты.Покупатель As [Покупатель $Справочник.Контрагенты],
   ПродажиОбороты.Номенклатура As [Номенклатура $Справочник.Номенклатура],
   RIGHT(ПродажиОбороты.ПозицияДокумента, 9) As [Документ $Документ],
   ПродажиОбороты.ВидДокумента Документ_вид,
   CASE WHEN :ВидЕдиницы = 1 THEN $СпрТовары.ОсновнаяЕдиница ELSE $СпрТовары.БазоваяЕдиница END As [Единица $Справочник.Единицы],
       SUM(ПродажиОбороты.СебестоимостьОборот)-SUM(ПродажиОбороты.СебестоимостьВОборот) As СуммаСебест,
       ROUND((SUM(ПродажиОбороты.КоличествоОборот)-SUM(ПродажиОбороты.КоличествоВОборот)) / CASE WHEN
                                                                                           CASE WHEN :ВидЕдиницы = 1 THEN $СпрТовары.ОсновнаяЕдиница ELSE $СпрТовары.БазоваяЕдиница END = $ПустойИД
                                                                                                 THEN 1
                                                                                                 ELSE  CASE WHEN $СпрЕдиницы.Коэффициент = 0 THEN 1 ELSE $СпрЕдиницы.Коэффициент END
                                                                                      END, 3) As СуммаКоличество,
   SUM(ПродажиОбороты.ПродСтоимостьОборот)-SUM(ПродажиОбороты.ПродСтоимостьВОборот) As СуммаПродСт
FROM
   $РегистрОбороты.Продажи(:НачДата, :КонДата~, Документ, ,
                                                Фирма IN (SELECT val FROM #ВТФирмы) AND Покупатель IN (SELECT val FROM #ВТПокупатели) AND 0 = 0 AND Номенклатура IN (SELECT val FROM #ВТТовары),
                                                (Фирма, Покупатель, Поставщик, Номенклатура),
                                                (Себестоимость, Количество, ПродСтоимость, СебестоимостьВ, КоличествоВ, ПродСтоимостьВ)) As ПродажиОбороты
INNER JOIN
   _1SJourn As Жур
ON
   Жур.Date_Time_IDDoc = ПродажиОбороты.ПозицияДокумента
INNER JOIN
   $Справочник.Фирмы As СпрФирмы
ON
   СпрФирмы.ID = ПродажиОбороты.Фирма
LEFT JOIN
   $Справочник.Контрагенты As СпрПокупатели
ON
   СпрПокупатели.ID = ПродажиОбороты.Покупатель
LEFT JOIN
   $Справочник.СвойстваКонтрагентов As СпрСвойстваПокупателей
ON
   СпрСвойстваПокупателей.ID = $СпрПокупатели.ОсновноеСвойство
LEFT JOIN
   $Справочник.Контрагенты As СпрПоставщики
ON
   СпрПоставщики.ID = ПродажиОбороты.Поставщик
LEFT JOIN
   $Справочник.СвойстваКонтрагентов As СпрСвойстваПоставщиков
ON
   СпрСвойстваПоставщиков.ID = $СпрПоставщики.ОсновноеСвойство
LEFT JOIN
   $Справочник.Номенклатура As СпрТовары
ON
   СпрТовары.ID = ПродажиОбороты.Номенклатура
LEFT JOIN
   $Справочник.СвойстваНоменклатуры As СпрСвойстваТовара
ON
   СпрСвойстваТовара.ID = $СпрТовары.ОсновноеСвойство
LEFT JOIN
   $Справочник.Единицы As СпрЕдиницы
ON
   СпрЕдиницы.ID = CASE WHEN :ВидЕдиницы = 1 THEN $СпрТовары.ОсновнаяЕдиница ELSE $СпрТовары.БазоваяЕдиница END
WHERE
   0 = 0
   GROUP BY
       ПродажиОбороты.Покупатель,
       ПродажиОбороты.Номенклатура,
   CASE WHEN :ВидЕдиницы = 1 THEN $СпрТовары.ОсновнаяЕдиница ELSE $СпрТовары.БазоваяЕдиница END,
   $СпрЕдиницы.Коэффициент,
   ПродажиОбороты.ПозицияДокумента,
   ПродажиОбороты.ВидДокумента,
   $СпрФирмы.ЮрЛицо,
   $СпрФирмы.УпрАналитика
20 ЧеловекДуши
 
14.07.11
08:14
(10)Ну тогда, кривой у тебя запрос :)
21 ЧеловекДуши
 
14.07.11
08:15
+(19)А теперь текст запроса на языке 1С :)
22 Mikeware
 
14.07.11
08:17
этто пипец...
23 ЧеловекДуши
 
14.07.11
08:17
+(19)Конструкцию типо "РегистрОбороты" лучше разложить.
Так будет выполняться быстрее.
А так эта конструкция "РегистрОбороты" предполагает вложенный запрос :)
24 DCKiller
 
14.07.11
08:18
(18) Всё знаешь - ну и хорошо. Я уже заценил, насколько ты крут. Будем дальше по делу или ЧСВ каждый свое раздувать?
25 DCKiller
 
14.07.11
08:19
(21)

Период с ДатаНачала по ДатаКонца;
Фирма            = Регистр.Продажи.Фирма;
УпрАналитика    = Регистр.Продажи.Фирма.УпрАналитика;
ЮрЛицо        = Регистр.Продажи.Фирма.ЮрЛицо;
Покупатель    = Регистр.Продажи.Покупатель;
СвойствоПок    = Регистр.Продажи.Покупатель.ОсновноеСвойство.ЗначениеСвойства;
Номенклатура    = Регистр.Продажи.Номенклатура;                
СвойствоТМЦ    = Регистр.Продажи.Номенклатура.ОсновноеСвойство.ЗначениеСвойства;
Поставщик        = Регистр.Продажи.Поставщик;
СвойствоПост    = Регистр.Продажи.Поставщик.ОсновноеСвойство.ЗначениеСвойства;
Себест      = Регистр.Продажи.Себестоимость;
Количество  = Регистр.Продажи.Количество;
ПродСт      = Регистр.Продажи.ПродСтоимость;
СебестВ     = Регистр.Продажи.СебестоимостьВ;
КоличествоВ = Регистр.Продажи.КоличествоВ;
ПродСтВ     = Регистр.Продажи.ПродСтоимостьВ;
Функция СуммаСебест      = Сумма(Себест);
Функция СуммаКоличество  = Сумма(Количество);
Функция СуммаПродСт      = Сумма(ПродСт);
Функция СуммаСебестВ     = Сумма(СебестВ);
Функция СуммаКоличествоВ = Сумма(КоличествоВ);
Функция СуммаПродСтВ     = Сумма(ПродСтВ);Условие (Фирма в ВыбРазделитель1);Условие (Номенклатура в ВыбТМЦ);Условие (Покупатель в ВыбПокупатель);Группировка Покупатель без групп;Группировка Номенклатура без групп;Группировка Документ;
26 DCKiller
 
14.07.11
08:19
(22) А ты бы как его написал?
27 ЧеловекДуши
 
14.07.11
08:19
А для чего тебе столько подключений ?
типо

"LEFT JOIN $Справочник.СвойстваКонтрагентов As СпрСвойстваПоставщиков ON СпрСвойстваПоставщиков.ID = $СпрПоставщики.ОсновноеСвойство
LEFT JOIN $Справочник.Номенклатура As СпрТовары ON СпрТовары.ID = ПродажиОбороты.Номенклатура
LEFT JOIN $Справочник.СвойстваНоменклатуры As СпрСвойстваТовара ON СпрСвойстваТовара.ID = $СпрТовары.ОсновноеСвойство
LEFT JOIN " и т.д.
28 ЧеловекДуши
 
14.07.11
08:20
+(27)И как было замечено, все они без команды (NOLOCK)... :D
29 DCKiller
 
14.07.11
08:21
(27) ну да, свойства в данном случае лишние... Они по идее нужны только если есть по ним условие отбора. Ща уберу.
30 DCKiller
 
14.07.11
08:21
(28) NOLOCK ускорит выполнение запроса?
31 Кириллка
 
14.07.11
08:23
прямой запрос тупит, видимо, когда кто-то что-то записывает/проводит? :)
32 ЧеловекДуши
 
14.07.11
08:23
(30)(NOLOCK) Позволит ускориться.
Без этой фигулинки, запрос пытается монополизировать таблицы.
33 Ёпрст
 
14.07.11
08:24
(19) ну и зачем тебе соединение с журналом, соединение со справочниками, типа фирмы, если ни в селект листе, ни в ветке where их нигде нет потом ?
34 DCKiller
 
14.07.11
08:26
(33) Все, ПОНЯЛ! Пошел оптимизировать.
35 viktor_vv
 
14.07.11
08:26
И вот это лучше вынеси во временую таблицу, где сформируй готовую таблицу с необходимым полем единицы.

$Справочник.Номенклатура As СпрТовары

с учетом

CASE WHEN :ВидЕдиницы = 1 THEN $СпрТовары.ОсновнаяЕдиница ELSE $СпрТовары.БазоваяЕдиница END
36 DCKiller
 
14.07.11
08:31
+34

Когда текст запроса генерится в модуле, условие по фильтру, сц_уко, было задано неправильно.
37 DCKiller
 
14.07.11
09:14
(32) А если к ПродажиОбороты прикрутить NOLOCK, он ругаеццо. Грит, "'ПродажиОбороты' has more columns than were specified in the column list"
38 Ёпрст
 
14.07.11
09:17
(37) ВТ и так в себе содержит этот хинт, не нужно его туда насильно пихать
39 DCKiller
 
14.07.11
09:18
(38) Понял, спс.
40 DCKiller
 
14.07.11
09:30
Всё, забегало! В-общем, NOLOCK рулит :)
А в файловой версии такой проблемы нет?
41 Ёпрст
 
14.07.11
10:13
(40) есть. Всё зависит, на чем написан будет прямой запрос.
На фоксе - есть свои "хинты" + нужно правильно писать запрос для попадания в индекс, на 1sqlite в индекс попадать не нужно специально (а в некоторых случаях нужно) и там всегда "по-умолчанию" нолок
42 DCKiller
 
14.07.11
11:37
(41) На фоксе - это там, где юзать DTOS?
43 Ёпрст
 
14.07.11
11:37
(42) да, там где используется vfp
Кaк может человек ожидaть, что его мольбaм о снисхождении ответит тот, кто превыше, когдa сaм он откaзывaет в милосердии тем, кто ниже его? Петр Трубецкой