Вход | Регистрация

1С:Предприятие :: 1С:Предприятие 7.7 и ранее

v7: SQLite медленней, чем стандартная выборка

v7: SQLite медленней, чем стандартная выборка
Я
   Sam1C
 
08.11.18 - 17:12
Нужно получение последнего документа определенного вида по контрагенту (имеется графа отбора):
1) Стандарт:
Док = СоздатьОбъект("Документ");
Док.ОбратныйПорядок(1);       Док.ВыбратьПоЗначению(,ТекущаяДата(),"Контрагент",пКонтрагент);
Пока Док.ПолучитьДокумент() = 1 Цикл  
    Если Док.Вид() <> пВид Тогда
        продолжить;    
    КонецЕсли;
   Если Док.ПолучитьАтрибут(ИД_Контрагент) = пКонтрагент Тогда
                прервать;
  КонецЕсли;
КонецЦикла;       
2) Запрос:
ТекстЗапроса = "SELECT 
        |  Док.IDDOC [Документ  $Документ." + пВид + "] 
        |, Док.Контрагент [Контрагент $Справочник.Контрагенты]
        |FROM [Документ." + пВид + "]  AS Док 
        |WHERE  (Док.Контрагент = :ВыбКонтрагент)  
        |ORDER BY Док.IDDOC DESC  LIMIT 1
        |";    
Если есть хоть один документ по контрагенту, то скорость их равно по 1 мсек, если документов нет, то Стандарт остается 1 мсек, а SQLite - 150 мсек (в 150 раз больше)
Получается Sqlite сканирует всю таблицу?
 
 
   Sam1C
 
1 - 08.11.18 - 17:24
(0) Способ SQLite мне больше по душе,не нужен цикл по проверке вида документа (если тысяча документов другого вида будут позже, может потянуть больше времени), не обязательна графа отбора и т.п. Может у кого будут мысли, как максимально быстро получить последний документ определенного вида по Контрагенту?
   v77
 
2 - 08.11.18 - 20:36
Да оно вроде и не должно быть быстрее. Через sqlite же теми же средствами 1с все работает. Да и сравнивать надо два запроса, а не запрос и простое чтение таблицы.
   АгентБезопаснойНацио
 
3 - 08.11.18 - 20:46
(1) ну так и ищи по графе отбора, а не по шапке документа. Будет быстро. Если надо - пример завтра кину.
   nicesc
 
4 - 08.11.18 - 20:49
Операция ORDER BY достаточно ресурсоемкая и здесь она не нужна.
Твой запрос не правильно отработает, если утренний документ сохранили в конец дня. Максимальный IDDOC будет у предыдущего документа.
Для того, что бы выдернуть последний документ тебе нужно обращаться к журналу документов.
   АгентБезопаснойНацио
 
5 - 08.11.18 - 20:55
(4) упорядочивание необходимо, иначе это будет "возьми первый попавшийся".
Но выборку надо делать не по шапке и журналу, а по ссылкам документов (1scrdoc) - там есть для этого все нужные индексы
   nicesc
 
6 - 08.11.18 - 21:08
(5) Если нужен один последний, то сортировать не нужна. Можно взять MAX(iddoc)
Через 1scrdoc не делал, попробую, спасибо за информацию. Через журнал можно сделать как то так:

ТекстЗапроса = "
  |SELECT
  |  MAX(Журнал.date||Журнал.time)
  |  ,Журнал.iddoc [Документ $Документ.Реализация]
  |FROM
  |  Журнал
  |INNER JOIN Документ_Реализация as докРеал
  | ON докРеал.iddoc = Журнал.iddoc 
  |   and докРеал.Контрагент = :ВыбКонтрагент
  |WHERE
  |    iddocdef = :ВидДокумента.Реализация";
   nicesc
 
7 - 08.11.18 - 21:15
похоже пора спать )
последнее условие избыточно, его можно выкинуть
   nicxxx
 
8 - 08.11.18 - 22:05
(6)(4) В MSSQL запросы TOP(1) ID ORDER BY и MAX(ID) обычно сводятся к одному плану запроса - seek/scan+sort+stream aggregate+select top 1. Следствие - нет разницы, как писать исходный запрос.
(0) Надо date_time_iddoc из журнала документов использовать - сортировать по нему, как в (6) советуют. Метод Док.ВыбратьПоЗначению() наверное так и делает.
   tesseract
 
9 - 08.11.18 - 23:15
А почему должно быть быстрее? Это просто простой перебор значений же. Если начать добавлять сложности всякие к запросу - будет заметен сильной прирост.

>>ORDER BY Док.IDDOC DESC  LIMIT 1

Ну так в любом случае будет Table Scan.  Хотя можно глянуть в плане запроса, но DESC - это в любом случае выборка во временное хранилище будет.
   Sam1C
 
10 - 09.11.18 - 08:45
(9) Не факт, так как если есть хоть один документ отрабатывает за 1 мсек (как будто берет первый попавшийся), если нету 150 мсек. Хотя с другой стороны все равно, надо выбрать все данные для упорядочивания, а не первый попавшийся.Может IDDOC индексное поле по которому физически упорядочены данные в таблицы и идет чтение с конца таблицы и после первого попавшего значения выдает результат.
 
 Рекламное место пустует
   Sam1C
 
11 - 09.11.18 - 08:49
(4) наоборот правильно отработает, мне нужен последний по периоду, а не  по созданию. Документ можно создать задним числом и он не будет уже являться последним по контрагенту.
   Sam1C
 
12 - 09.11.18 - 08:50
(11) + iddoc я так думаю при смене даты не меняется ж?
   Sam1C
 
13 - 09.11.18 - 08:52
(3) Буду благодарен за пример!
   Sserj
 
14 - 09.11.18 - 08:53
Да о чем вообще разговор.
1С-ный запрос знает про графу отбора, а в прямой запрос делается по таблице документа в которой контрагент не индексирован.
Прямой запрос нужно делать по таблице 1SCRDOC там индекс и на контраоента и на позицию документа есть.
   Djelf
 
15 - 09.11.18 - 08:54
(10) Как раз факт.
order by desc не приводит к  временной таблице, т.к. движок умеет выбирать записи в обратном порядке по индексу и необходимости в дополнительной сортировки нет
но индекса по контрагенту тоже нет, поэтому по контрагенту идет чтение всей таблицы
но если контрагент есть то дальнейшие записи из-за limit 1 перебирать нет необходимости
вот и получается что когда контрагента нет, приходится перебирать все записи
   АгентБезопаснойНацио
 
16 - 09.11.18 - 08:56
(14) нормальный прямой запрос тоже знает про графу отбора
   Djelf
 
17 - 09.11.18 - 11:31
Вот как то так для 1sqlite
SELECT
    max(idx_MDID_PARENTVAL_CHILDDATE_CHILDTIME_CHILDID ) AS MAXDDATE
    ,Журнал.IDDOC [Документ :Документ.Реализация]
    ,Отбор.PARENTVAL [Контрагент :Неопределенный]
FROM __1S_CRDOC AS Отбор
LEFT JOIN Журнал ON Журнал.IDDOC=Отбор.CHILDID
WHERE Отбор.MDID=:ГрафаОтбора.Контрагент
    AND Отбор.PARENTVAL = /users.php?id=6154" target="_blank" class="registered-user">Контрагент
    AND Журнал.IDDOCDEF=:ВидДокумента.Реализация


Контрагент должен быть id23 
УстановитьПараметр(/users.php?id=6154" target="_blank" class="registered-user">Контрагент,Контрагент,-1)

P.S. на оригинальной 1.0.2.6 и ниже может не сработать из за отсутствия оптимизации по max(). Не проверял. А на 1sqlite посвежее работает, брать тут: http://catalog.mista.ru/public/559826/
   АгентБезопаснойНацио
 
18 - 09.11.18 - 11:33
(17) а не проще ему взять класс ПрямойЗапрос, и не париться?
   Djelf
 
19 - 09.11.18 - 11:49
(18) Не проще. В ПрямомЗапросе нет отдельной оптимизации по получению последнего значения в таблице ссылок по графе отбора.
   АгентБезопаснойНацио
 
20 - 09.11.18 - 11:58
там вообще оптимизаций мало. но хотя бы есть описание "по каким таблицам искать" и как.

Список тем форума
Рекламное место пустует  Рекламное место пустует
ВНИМАНИЕ! Если вы потеряли окно ввода сообщения, нажмите Ctrl-F5 или Ctrl-R или кнопку "Обновить" в браузере.
Рекламное место пустует