Имя: Пароль:
1C
1C 7.7
v7: Производительность запроса к регистрам
,
0 ildary
 
17.12.14
14:38
Уважаемые специалисты, подскажите пожалуйста, почему стандартный запрос к регистру остатков выполняется быстрее 1sqlite (база DBF)?
Стандартный запрос:

Период с НачДата по КонДата;

Склад        = Регистр.ОстаткиТМЦ.Склад;
Номенклатура = Регистр.ОстаткиТМЦ.Номенклатура;
Количество   = Регистр.ОстаткиТМЦ.Количество;

Функция КоличествоНачОст = НачОст( Количество );
Функция КоличествоКонОст = КонОст( Количество );

Группировка Номенклатура без групп;
Условие ( НЕ ( Номенклатура в спсНомраИсключить ) );
Условие( Склад = ВыбСклад );

Прямой запрос:
SELECT
      Рег.Номенклатура [Номенклатура $Справочник.Номенклатура],
      SUM(Рег.КоличествоНачОст) [КоличествоНачОст $Число],
      SUM(Рег.КоличествоНачОст+Рег.КоличествоПриход-Рег.КоличествоРасход) [КоличествоКонОст $Число]
From
(
SELECT
      Итоги.Номенклатура Номенклатура
      ,Итоги.Количество  КоличествоНачОст
      ,0          КоличествоПриход
      ,0         КоличествоРасход
FROM
     [РегистрИтоги.ОстаткиТМЦ] AS Итоги
WHERE
      (Итоги.period = :ПредПериод)  AND (Итоги.Склад = :ВыбСклад) AND (Итоги.Номенклатура not in (select val from НоменклатураОтб ) )

UNION ALL
SELECT
       Движения.Номенклатура
       ,Движения.Количество * (1 - Движения.debkred * 2)
       ,0
       ,0
FROM
     [Регистр.ОстаткиТМЦ]       AS Движения
INNER Join [Журнал] Жур ON Жур.iddoc = Движения.iddoc and Жур.date BETWEEN :НачПериод And :КонПериод
WHERE
      (Движения.Склад = :ВыбСклад) AND (Движения.Номенклатура not in (select val from НоменклатураОтб ))

UNION ALL
SELECT
       Движения2.Номенклатура
       ,0
       ,Движения2.Количество*(1-Движения2.Debkred)
       ,Движения2.Количество*Движения2.Debkred
FROM
     [Регистр.ОстаткиТМЦ] Движения2
INNER Join [Журнал] Жур2 ON Жур2.iddoc = Движения2.iddoc and Жур2.date BETWEEN :НачДата And :КонДата
WHERE
      (Движения2.Склад = :ВыбСклад) AND (Движения2.Номенклатура not in (select val from НоменклатураОтб ) )
) Рег

Group by Рег.Номенклатура
1 ildary
 
18.12.14
09:09
Заметил, что если данный прямой запрос выполнить за последний месяц, либо выполнить его помесячно за год - то прямой запрос выполняется быстрее обычного, а проблема начинается, если надо получить остатки на 01.06.14 и 18.12.14. Может для такого случая надо этот запрос выполнить как-нибудь по другому?
2 Godofsin
 
18.12.14
09:12
Быстрее - это насколько?
3 ildary
 
18.12.14
09:16
(2) Приблизительно в 2 раза дольше.

         Прямой запрос  Обычный запрос

За последний месяц: 2с   4с
По месяцам за год:  9с  18с
За год в целом:    18с   9с
4 dk
 
18.12.14
09:48
штатный запрос иногда делает выборку по 1сджорнал и иннер к таблице регистра типа

    |SELECT
    |    $СпрСклад.Подразделение                Подразделение
    |    , CASE WHEN ($СпрСклад.ТипСклада = :ВыбМПР) THEN 0 ELSE $ТоварыПоСкладам.Оборот END        ВыручкаОПТ
    |    , CASE WHEN ($СпрСклад.ТипСклада = :ВыбМПР) THEN $ТоварыПоСкладам.Оборот ELSE 0 END        ВыручкаМПР
    |    , CASE WHEN ($СпрСклад.ТипСклада = :ВыбМПР) THEN 0 ELSE $ТоварыПоСкладам.Списание END    СебестоимостьОПТ
    |    , CASE WHEN ($СпрСклад.ТипСклада = :ВыбМПР) THEN $ТоварыПоСкладам.Списание ELSE 0 END    СебестоимостьМПР
    |    , DATEADD(MONTH, DATEDIFF(MONTH, 0, Cast(Left(ТоварыПоСкладам.DATE_TIME_IDDOC, 8) AS datetime)), 0) Месяц
    |FROM _1SJOURN AS Жур With (NOLOCK)
    |    INNER JOIN $Регистр.ТоварыПоСкладам AS ТоварыПоСкладам With (NOLOCK)  ON ТоварыПоСкладам.IDDoc = Жур.IDDoc
    |    INNER JOIN $Справочник.МестаХранения AS СпрСклад With (NOLOCK) ON $ТоварыПоСкладам.Склад = СпрСклад.ID
    |WHERE
    |    (Жур.Date_Time_IDDoc BETWEEN :НачДата AND :КонДата~)
    |    AND ($ФлагРегистра.ТоварыПоСкладам = 1)
    |    AND ((Жур.CLOSED & 1) = 1)
    |    AND ($ТоварыПоСкладам.Товар <> :ВыбТовар)
    |    AND (($ТоварыПоСкладам.Оборот <> 0) OR ($ТоварыПоСкладам.Списание <> 0))
5 Djelf
 
19.12.14
12:37
Движок sqlite староват, в нем IN не использует индексы
Например, аналогичный запрос с IN

SELECT
РПН.Номенклатура     [ID $Справочник.Номенклатура]
FROM Регистр_ПартииНаличие AS РПН
WHERE РПН.Номенклатура  IN (SELECT ID FROM Справочник_Номенклатура AS СН WHERE СН.DESCR LIKE '%пиво%')

На sqlite 1.0.26 с движком sqlite 3.7.10 выполняется 3868мс, а на движке 3.7.17 где есть оптимизация in - 48мс
6 ildary
 
22.12.14
10:12
Я правильно понимаю, что если в IN передается небольшой список значений (2-4 значения) - то оптимальней будет переписать запрос на (аа=1) OR (аа=2) OR (аа=3)?
7 antoneus
 
22.12.14
10:26
(6) емнип, план в обоих случаях одинаковый будет
8 Djelf
 
22.12.14
12:56
Лучше во временную таблицу их и inner join либо еще варианты отсюда:
9 Djelf
 
22.12.14
12:56
10 ildary
 
22.12.14
13:08
Спасибо за науку, будем посмотреть.
11 ildary
 
22.12.14
13:10
+(10) еще хотел спросить - где почитать доку про помещение СЗ во временную таблицу?
12 Djelf
 
22.12.14
13:18
в документации https://snegopat.ru/downloads/1sqlite/
УложитьОбъекты(Объект, ИмяТаблицы, [КакПостоянную], [Иерархия])
еще можно попробовать 1sqlite на движке 3.7.17 http://www.1cpp.ru/forum/YaBB.pl?num=1418818749/4#4
ошибок пока не заметил
13 ildary
 
22.12.14
13:26
(12) благодарю за науку, значит стоит попробовать  1sqlite_3_7_17_bf1.zip?
14 Djelf
 
22.12.14
13:43
я обновлял движок чтобы in заработал, а то у меня один запрос ну такой мутный получался, что проще было движок sqlite поменять ;)
15 ildary
 
22.12.14
14:14
(14) суровый подход, снимаю шляпу :)
Здесь можно обсудить любую тему при этом оставаясь на форуме для 1Сников, который нужен для работы. Ymryn