|
v7: SQLite медленней, чем стандартная выборка | ☑ | ||
---|---|---|---|---|
0
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 сканирует всю таблицу? |
|||
1
Sam1C
08.11.18
✎
17:24
|
(0) Способ SQLite мне больше по душе,не нужен цикл по проверке вида документа (если тысяча документов другого вида будут позже, может потянуть больше времени), не обязательна графа отбора и т.п. Может у кого будут мысли, как максимально быстро получить последний документ определенного вида по Контрагенту?
|
|||
2
v77
08.11.18
✎
20:36
|
Да оно вроде и не должно быть быстрее. Через sqlite же теми же средствами 1с все работает. Да и сравнивать надо два запроса, а не запрос и простое чтение таблицы.
|
|||
3
АгентБезопасной Нацио
08.11.18
✎
20:46
|
(1) ну так и ищи по графе отбора, а не по шапке документа. Будет быстро. Если надо - пример завтра кину.
|
|||
4
nicesc
08.11.18
✎
20:49
|
Операция ORDER BY достаточно ресурсоемкая и здесь она не нужна.
Твой запрос не правильно отработает, если утренний документ сохранили в конец дня. Максимальный IDDOC будет у предыдущего документа. Для того, что бы выдернуть последний документ тебе нужно обращаться к журналу документов. |
|||
5
АгентБезопасной Нацио
08.11.18
✎
20:55
|
(4) упорядочивание необходимо, иначе это будет "возьми первый попавшийся".
Но выборку надо делать не по шапке и журналу, а по ссылкам документов (1scrdoc) - там есть для этого все нужные индексы |
|||
6
nicesc
08.11.18
✎
21:08
|
(5) Если нужен один последний, то сортировать не нужна. Можно взять MAX(iddoc)
Через 1scrdoc не делал, попробую, спасибо за информацию. Через журнал можно сделать как то так: ТекстЗапроса = " |SELECT | MAX(Журнал.date||Журнал.time) | ,Журнал.iddoc [Документ $Документ.Реализация] |FROM | Журнал |INNER JOIN Документ_Реализация as докРеал | ON докРеал.iddoc = Журнал.iddoc | and докРеал.Контрагент = :ВыбКонтрагент |WHERE | iddocdef = :ВидДокумента.Реализация"; |
|||
7
nicesc
08.11.18
✎
21:15
|
похоже пора спать )
последнее условие избыточно, его можно выкинуть |
|||
8
nicxxx
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) советуют. Метод Док.ВыбратьПоЗначению() наверное так и делает. |
|||
9
tesseract
08.11.18
✎
23:15
|
А почему должно быть быстрее? Это просто простой перебор значений же. Если начать добавлять сложности всякие к запросу - будет заметен сильной прирост.
>>ORDER BY Док.IDDOC DESC LIMIT 1 Ну так в любом случае будет Table Scan. Хотя можно глянуть в плане запроса, но DESC - это в любом случае выборка во временное хранилище будет. |
|||
10
Sam1C
09.11.18
✎
08:45
|
(9) Не факт, так как если есть хоть один документ отрабатывает за 1 мсек (как будто берет первый попавшийся), если нету 150 мсек. Хотя с другой стороны все равно, надо выбрать все данные для упорядочивания, а не первый попавшийся.Может IDDOC индексное поле по которому физически упорядочены данные в таблицы и идет чтение с конца таблицы и после первого попавшего значения выдает результат.
|
|||
11
Sam1C
09.11.18
✎
08:49
|
(4) наоборот правильно отработает, мне нужен последний по периоду, а не по созданию. Документ можно создать задним числом и он не будет уже являться последним по контрагенту.
|
|||
12
Sam1C
09.11.18
✎
08:50
|
(11) + iddoc я так думаю при смене даты не меняется ж?
|
|||
13
Sam1C
09.11.18
✎
08:52
|
(3) Буду благодарен за пример!
|
|||
14
Sserj
09.11.18
✎
08:53
|
Да о чем вообще разговор.
1С-ный запрос знает про графу отбора, а в прямой запрос делается по таблице документа в которой контрагент не индексирован. Прямой запрос нужно делать по таблице 1SCRDOC там индекс и на контраоента и на позицию документа есть. |
|||
15
Djelf
09.11.18
✎
08:54
|
(10) Как раз факт.
order by desc не приводит к временной таблице, т.к. движок умеет выбирать записи в обратном порядке по индексу и необходимости в дополнительной сортировки нет но индекса по контрагенту тоже нет, поэтому по контрагенту идет чтение всей таблицы но если контрагент есть то дальнейшие записи из-за limit 1 перебирать нет необходимости вот и получается что когда контрагента нет, приходится перебирать все записи |
|||
16
АгентБезопасной Нацио
09.11.18
✎
08:56
|
(14) нормальный прямой запрос тоже знает про графу отбора
|
|||
17
Djelf
09.11.18
✎
11:31
|
Вот как то так для 1sqlite
Контрагент должен быть id23 УстановитьПараметр(Контрагент,Контрагент,-1) P.S. на оригинальной 1.0.2.6 и ниже может не сработать из за отсутствия оптимизации по max(). Не проверял. А на 1sqlite посвежее работает, брать тут: http://catalog.mista.ru/public/559826/ |
|||
18
АгентБезопасной Нацио
09.11.18
✎
11:33
|
(17) а не проще ему взять класс ПрямойЗапрос, и не париться?
|
|||
19
Djelf
09.11.18
✎
11:49
|
(18) Не проще. В ПрямомЗапросе нет отдельной оптимизации по получению последнего значения в таблице ссылок по графе отбора.
|
|||
20
АгентБезопасной Нацио
09.11.18
✎
11:58
|
там вообще оптимизаций мало. но хотя бы есть описание "по каким таблицам искать" и как.
|
Форум | Правила | Описание | Объявления | Секции | Поиск | Книга знаний | Вики-миста |