Переключение на Главную Страницу Страницы: [1]  ОтправитьПечать
Горячая тема (более 10 ответов) Нужна помощь в оптимизации запроса на 1sqlite (число прочтений - 5092 )
k_petrovich
Junior Member
**
Отсутствует


1C++ rocks!

Сообщений: 17
Зарегистрирован: 01. Марта 2012
Пол: Мужской
Нужна помощь в оптимизации запроса на 1sqlite
10. Апреля 2012 :: 11:45
Печать  
1c DBF + 1c++ 3.2.2.0 + 1sqlite 1.0.2.6  

База = СоздатьОбъект("SQLiteBase");
   База.Открыть(":memory:");
   Запрос = База.НовыйЗапрос();
   Запрос.ВыполнитьЗапрос("PRAGMA journal_mode = WAL");
     
   Запрос.ВыполнитьЗапрос("create virtual table _1SENTRY using dbeng(_1S.Entry)");

ТекстЗапроса = "SELECT                            
   |  substr(Проводки.DTSC2,1,9) as [Партия_вид:Справочник.Партии],
     |  (0) as КолвоОстаток,
   |  (CAST(Проводки.AMOUNT as NUMERIC(15,3))) as КолвоДебет,
   |  (0) as КолвоКредит
   | FROM
   |  _1SENTRY as Проводки
   | WHERE
   |  (Проводки.idx_DATE_TIME_DOCID_NUMBER_CORNO >= @ДатаПроводкиНач) AND
   |  (Проводки.idx_DATE_TIME_DOCID_NUMBER_CORNO < @ДатаПроводкиКон) AND  
   |  (Проводки.ACCDTID = @Счет) AND (Проводки.DTSC0 = @Склад) AND (Проводки.DTSC1 = @ТМЦ)";

Запрос.Подготовить(ТекстЗапроса);

Запрос.УстановитьПараметр("@Склад",Склад);
Запрос.УстановитьПараметр("@ТМЦ",ТМЦ);
Запрос.УстановитьПараметр("@Счет",ТМЦ.Счет);

Запрос.УстановитьПараметр("@ДатаПроводкиНач",НачКвартала(Док.ДатаДок));
),1);

ТЗ = Запрос.Выполнить();


Вот че говорит отладчик:

Подбор индекса для таблицы 1SENTRY:
Ограничения: DATETIME[dx_DATE_TIME_DOCID_NUMBER_CORNO]>=; DATETIME[dx_DATE_TIME_DOCID_NUMBER_CORNO]<; ACCDTID=; DTSC0=; DTSC1=;
Найдено в кэше
Выбран индекс DATETIME: DTOS(DATE)+TIME+DOCID+STR(NUMBER,5)+STR(CORNO,5)
Стоимость: 20

В тестовой базе (монопольно) время выполнения для 36 ТМЦ:
0.174

В реальной базе в терминале:
> 5

причем штатный СоздатьОбъект("БухгалтерскиеИтоги") делает эту задачу в терминале быстрее

я наверно че-то не так делаю?
  
Наверх
 
IP записан
 
Dmitry The Wing
God Member
*****
Отсутствует


1C++ rocks!

Сообщений: 839
Местоположение: Где-то в Сибири
Зарегистрирован: 18. Августа 2009
Пол: Мужской
Re: Нужна помощь в оптимизации запроса на 1sqlite
Ответ #1 - 11. Апреля 2012 :: 01:30
Печать  
На вопрос ответить не смогу, но совет дам:
Логические условия обычно выполняются в порядке написания, т.е. правильнее будет сначала поставить проверку на точные значения, а уже потом проверять интервал дат. Это раз.
И два - лучше использовать оператор BETWEEN, чем два сравнения.
По идее, это уже должно ускорить выполнение запроса при большом количестве данных.
  
Наверх
 
IP записан
 
leshik
1c++ donor
Отсутствует



Сообщений: 820
Местоположение: Пятигорск
Зарегистрирован: 22. Апреля 2007
Пол: Мужской
Re: Нужна помощь в оптимизации запроса на 1sqlite
Ответ #2 - 11. Апреля 2012 :: 04:59
Печать  
Надо использовать ВТ из класса ПрямойЗапрос так как у автора не задействована таблица отбора проводок по субконто
  
Наверх
IP записан
 
k_petrovich
Junior Member
**
Отсутствует


1C++ rocks!

Сообщений: 17
Зарегистрирован: 01. Марта 2012
Пол: Мужской
Re: Нужна помощь в оптимизации запроса на 1sqlite
Ответ #3 - 11. Апреля 2012 :: 05:05
Печать  
| WHERE
|  (Проводки.ACCDTID = @Счет) and (Проводки.DTSC0 = @Склад) and (Проводки.DTSC1 = @ТМЦ) and
|  (Проводки.idx_DATE_TIME_DOCID_NUMBER_CORNO BETWEEN @ДатаПроводкиНач AND @ДатаПроводкиКон)

ничего не поменялось
  
Наверх
 
IP записан
 
k_petrovich
Junior Member
**
Отсутствует


1C++ rocks!

Сообщений: 17
Зарегистрирован: 01. Марта 2012
Пол: Мужской
Re: Нужна помощь в оптимизации запроса на 1sqlite
Ответ #4 - 11. Апреля 2012 :: 05:06
Печать  
leshik писал(а) 11. Апреля 2012 :: 04:59:
Надо использовать ВТ из класса ПрямойЗапрос так как у автора не задействована таблица отбора проводок по субконто


а без ВТ можно? как задействовать эту таблицу?
  
Наверх
 
IP записан
 
vandalsvq
1c++ power user
Отсутствует


Я всего лишь als-особиратель
;-)

Сообщений: 2487
Местоположение: Уфа
Зарегистрирован: 18. Июля 2007
Пол: Мужской
Re: Нужна помощь в оптимизации запроса на 1sqlite
Ответ #5 - 11. Апреля 2012 :: 07:34
Печать  
Описание таблиц БУ - тут
Посмотри в сторону таблиц _1SBKTTLC, _1SBKTTL
Возможно пригодится _1SACCSEL
Но могу сказать что большой пользы от использования _1SBKTTLC и _1SACCSEL в дбф + скульлайт мне извлечь в ходе экспериментов не удалось. А вот _1SBKTTL бесспорно необходимо по возможности использовать
  

Отхожу от дел. Долго и мучительно.
Наверх
IP записан
 
k_petrovich
Junior Member
**
Отсутствует


1C++ rocks!

Сообщений: 17
Зарегистрирован: 01. Марта 2012
Пол: Мужской
Re: Нужна помощь в оптимизации запроса на 1sqlite
Ответ #6 - 11. Апреля 2012 :: 07:40
Печать  
ну _1SBKTTL само-собой у меня в данном запросе НачДата береться с начала квартала. Удивляет то что даже за период меньше месяца запрос делаеться по одному ТМЦ около 0.1 сек, а если ТМЦ штук 50, то и получает 5 сек
  
Наверх
 
IP записан
 
Eprst
God Member
*****
Отсутствует



Сообщений: 3397
Зарегистрирован: 08. Октября 2007
Re: Нужна помощь в оптимизации запроса на 1sqlite
Ответ #7 - 11. Апреля 2012 :: 07:42
Печать  
(0) не советую юзать пока qlite 1.0.2.6   

в нём есть ошибки, приводящие к вылету 1с
  
Наверх
 
IP записан
 
k_petrovich
Junior Member
**
Отсутствует


1C++ rocks!

Сообщений: 17
Зарегистрирован: 01. Марта 2012
Пол: Мужской
Re: Нужна помощь в оптимизации запроса на 1sqlite
Ответ #8 - 11. Апреля 2012 :: 08:07
Печать  
а какой стабильный?

вот последние замеры:
через 1sqlite время 3 сек
через VFPOLEDB - 0.2 сек

просто мне нужны запросы в монопольном режиме поэтому и остановился на 1sqlite
  
Наверх
 
IP записан
 
Eprst
God Member
*****
Отсутствует



Сообщений: 3397
Зарегистрирован: 08. Октября 2007
Re: Нужна помощь в оптимизации запроса на 1sqlite
Ответ #9 - 11. Апреля 2012 :: 08:27
Печать  
24 хотя бы
ЗЫ: vfp сто лет в обед  умеет работать с монопольными базами, при правильном тексте запроса с попаданием в индекс обгоняет в разы 1sqlite на некоторых запросах, особенно в использовании group by

Просто 1sqlite запрос проще писать + есть свои вкусности, типа провайдера для табличного поля и т.д.
  
Наверх
 
IP записан
 
k_petrovich
Junior Member
**
Отсутствует


1C++ rocks!

Сообщений: 17
Зарегистрирован: 01. Марта 2012
Пол: Мужской
Re: Нужна помощь в оптимизации запроса на 1sqlite
Ответ #10 - 11. Апреля 2012 :: 08:59
Печать  
ну заплатку от hogik я не нашел для VFP
  
Наверх
 
IP записан
 
Eprst
God Member
*****
Отсутствует



Сообщений: 3397
Зарегистрирован: 08. Октября 2007
Re: Нужна помощь в оптимизации запроса на 1sqlite
Ответ #11 - 11. Апреля 2012 :: 09:31
Печать  
в папке BIN переименуешь dbeng32.dll в dbeng33.dll и положишь туда же содержимое этого архива.
Наслаждайся.
  

DBEng32_8007.zip ( 40 KB | Загрузки )
Наверх
 
IP записан
 
k_petrovich
Junior Member
**
Отсутствует


1C++ rocks!

Сообщений: 17
Зарегистрирован: 01. Марта 2012
Пол: Мужской
Re: Нужна помощь в оптимизации запроса на 1sqlite
Ответ #12 - 11. Апреля 2012 :: 09:53
Печать  
спасибо, а то в нете все ссылки мертвые
  
Наверх
 
IP записан
 
Eprst
God Member
*****
Отсутствует



Сообщений: 3397
Зарегистрирован: 08. Октября 2007
Re: Нужна помощь в оптимизации запроса на 1sqlite
Ответ #13 - 11. Апреля 2012 :: 09:58
Печать  
ну и.. не забываем это читать, если фоксовый запрос будешь писать:
http://www.1cpp.ru/forum/YaBB.pl?num=1184317705
  
Наверх
 
IP записан
 
k_petrovich
Junior Member
**
Отсутствует


1C++ rocks!

Сообщений: 17
Зарегистрирован: 01. Марта 2012
Пол: Мужской
Re: Нужна помощь в оптимизации запроса на 1sqlite
Ответ #14 - 11. Апреля 2012 :: 11:55
Печать  
подитожим:
список из 60 ТМЦ, получаю остатки по партиям на дату документа
выбрал документ где-то конец квартала

OLEDB - 4.632
1sqlite - 70.594
и штатный БухгалтерсиеИтоги - 8.129

поможете разобраться в чем прикол?

мог бы выбрать самый быстрый вариант, просто интересно почему так проигрывает 1sqlte и почему OLEDB выигрывает всего-лишь в 2 раза?
  
Наверх
 
IP записан
 
Eprst
God Member
*****
Отсутствует



Сообщений: 3397
Зарегистрирован: 08. Октября 2007
Re: Нужна помощь в оптимизации запроса на 1sqlite
Ответ #15 - 11. Апреля 2012 :: 12:22
Печать  
тексты запросов то покажи, для начала
  
Наверх
 
IP записан
 
k_petrovich
Junior Member
**
Отсутствует


1C++ rocks!

Сообщений: 17
Зарегистрирован: 01. Марта 2012
Пол: Мужской
Re: Нужна помощь в оптимизации запроса на 1sqlite
Ответ #16 - 11. Апреля 2012 :: 12:34
Печать  
1SQLITE
Если НачКвартала(Док.ДатаДок) = НачМесяца(Док.ДатаДок) Тогда
//первый месяц квартала  
СтрСальдо = "SUM(CAST(Остатки.SD as NUMERIC(15,3)))";
ИначеЕсли ДобавитьМесяц(НачКвартала(Док.ДатаДок), 1) = НачМесяца(Док.ДатаДок) Тогда    
//второй  
СтрСальдо = "SUM(CAST(Остатки.SD as NUMERIC(15,3))+(CAST(Остатки.OBDT1 as NUMERIC(15,3))-CAST(Остатки.OBKT1 as NUMERIC(15,3))))";
ИначеЕсли ДобавитьМесяц(НачКвартала(Док.ДатаДок), 2) = НачМесяца(Док.ДатаДок) Тогда
//третий  
СтрСальдо = "SUM(CAST(Остатки.SD as NUMERIC(15,3))+(CAST(Остатки.OBDT1 as NUMERIC(15,3))-CAST(Остатки.OBKT1 as NUMERIC(15,3)))+(CAST(Остатки.OBDT2 as NUMERIC(15,3))-CAST(Остатки.OBKT2 as NUMERIC(15,3))))";
КонецЕсли;
                         
ТекстЗапроса="
|SELECT
| substr(Остатки.SC2, 1, 9) as [Партия_вид:Справочник.Партии],
| "+СтрСальдо+" as КолвоОстаток,
| SUM(0) as КолвоДебет,
| SUM(0) as КолвоКредит
|FROM
| _1SBKTTL AS Остатки
|WHERE
| (Остатки.DATE = @ДатаПроводкиНач) AND (Остатки.SP4373 = @НашаФирма) AND (Остатки.KIND = '3') AND
| (Остатки.ACCID = @Счет) AND (Остатки.SC0 = @Склад) AND (Остатки.SC1 = @ТМЦ)
|GROUP BY
| Остатки.SC2
|      
|UNION ALL
|      
|SELECT      
|  substr(Проводки.KTSC2,1,9) as [Партия_вид:Справочник.Партии],      
|  SUM(0) as КолвоОстаток,
|  SUM(0) as КолвоДебет,
|  SUM(CAST(Проводки.AMOUNT as NUMERIC(15,3))) as КолвоКредит
| FROM
|  _1SENTRY as Проводки
| WHERE
|  (Проводки.ACCKTID = @Счет) AND (Проводки.KTSC0 = @Склад) AND (Проводки.KTSC1 = @ТМЦ) AND  
|  (Проводки.idx_DATE_TIME_DOCID_NUMBER_CORNO BETWEEN @ДатаПроводкиНач AND @ДатаПроводкиКон)
| GROUP BY
|  Проводки.KTSC2
|
| UNION ALL    
|
| SELECT                            
|  substr(Проводки.DTSC2,1,9) as [Партия_вид:Справочник.Партии],
|  (0) as КолвоОстаток,
|  (CAST(Проводки.AMOUNT as NUMERIC(15,3))) as КолвоДебет,
|  (0) as КолвоКредит
| FROM
|  _1SENTRY as Проводки
| WHERE            
|  (Проводки.ACCDTID = @Счет) and (Проводки.DTSC0 = @Склад) and (Проводки.DTSC1 = @ТМЦ) and
|  (Проводки.idx_DATE_TIME_DOCID_NUMBER_CORNO BETWEEN @ДатаПроводкиНач AND @ДатаПроводкиКон)
| GROUP BY
|  Проводки.DTSC2
|";

OLEDB
Если НачКвартала(Док.ДатаДок) = НачМесяца(Док.ДатаДок) Тогда
//первый месяц квартала  
СтрСальдо = "SUM(CAST(Остатки.SD as NUMERIC(15,3)))";
ИначеЕсли ДобавитьМесяц(НачКвартала(Док.ДатаДок), 1) = НачМесяца(Док.ДатаДок) Тогда    
//второй  
СтрСальдо = "SUM(CAST(Остатки.SD as NUMERIC(15,3))+(CAST(Остатки.OBDT1 as NUMERIC(15,3))-CAST(Остатки.OBKT1 as NUMERIC(15,3))))";
ИначеЕсли ДобавитьМесяц(НачКвартала(Док.ДатаДок), 2) = НачМесяца(Док.ДатаДок) Тогда
//третий  
СтрСальдо = "SUM(CAST(Остатки.SD as NUMERIC(15,3))+(CAST(Остатки.OBDT1 as NUMERIC(15,3))-CAST(Остатки.OBKT1 as NUMERIC(15,3)))+(CAST(Остатки.OBDT2 as NUMERIC(15,3))-CAST(Остатки.OBKT2 as NUMERIC(15,3))))";
КонецЕсли;
                 
ТекстЗапроса = "SELECT
| Остатки.SC2 as [Партия $Справочник.Партии],                  
| "+СтрСальдо+" as [КолвоОстаток $Число],
| SUM(0) as [КолвоДебет $Число],
| SUM(0) as [КолвоКредит $Число]
|FROM
| 1SBKTTL AS Остатки
|WHERE
| тки.SC1+Остатки.SC2+Остатки.CURRID LIKE
| _______'+'_________'))
|GROUP BY
| Остатки.SC2
|
| UNION ALL
|
|SELECT            
|  Проводки.KTSC2 as [Партия $Справочник.Партии]                  
|  , SUM(0) as [КолвоОстаток $Число]
|  , SUM(0) as [КолвоДебет $Число]
|  , SUM(Проводки.AMOUNT) as [КолвоКредит $Число]
|FROM  
|  1SENTRY as Проводки    
|Where
|  (Проводки.ACCKTID = :Счет) and (Проводки.KTSC0 = :Склад) and (Проводки.KTSC1 = :ТМЦ) and
| оводки.CORNO,5)
| BETWEEN (DTOS(:ДатаПроводкиНач~~)+'      '+'         '+'     '+'     ') AND (:ДатаПроводкиКон~+'ZZZZZ'+'ZZZZZ'))
| GROUP BY
|  Проводки.KTSC2
|
| UNION ALL
|
|SELECT            
|  Проводки.DTSC2 as [Партия $Справочник.Партии]                  
|  , SUM(0) as [КолвоОстаток $Число]
|  , SUM(Проводки.AMOUNT) as [КолвоДебет $Число]
|  , SUM(0) as [КолвоКредит $Число]
|FROM  
|  1SENTRY as Проводки    
|Where
|  (Проводки.ACCDTID = :Счет) and (Проводки.DTSC0 = :Склад) and (Проводки.DTSC1 = :ТМЦ) and
| оводки.CORNO,5)
| BETWEEN (DTOS(:ДатаПроводкиНач~~)+'      '+'         '+'     '+'     ') AND (:ДатаПроводкиКон~+'ZZZZZ'+'ZZZZZ'))
| GROUP BY
|  Проводки.DTSC2
|";
  
Наверх
 
IP записан
 
k_petrovich
Junior Member
**
Отсутствует


1C++ rocks!

Сообщений: 17
Зарегистрирован: 01. Марта 2012
Пол: Мужской
Re: Нужна помощь в оптимизации запроса на 1sqlite
Ответ #17 - 12. Апреля 2012 :: 06:44
Печать  
неужели никому не интересно?
  
Наверх
 
IP записан
 
Eprst
God Member
*****
Отсутствует



Сообщений: 3397
Зарегистрирован: 08. Октября 2007
Re: Нужна помощь в оптимизации запроса на 1sqlite
Ответ #18 - 12. Апреля 2012 :: 07:20
Печать  
неа..

С виду всё правильно.

Разве что не используешь табличку отбора по счетам
+ в одном запросе отрезаешь часть строки через субстринг, а в другом и так типизируешь..
  
Наверх
 
IP записан
 
k_petrovich
Junior Member
**
Отсутствует


1C++ rocks!

Сообщений: 17
Зарегистрирован: 01. Марта 2012
Пол: Мужской
Re: Нужна помощь в оптимизации запроса на 1sqlite
Ответ #19 - 12. Апреля 2012 :: 08:22
Печать  
1SACCSEL пуста
  
Наверх
 
IP записан
 
Eprst
God Member
*****
Отсутствует



Сообщений: 3397
Зарегистрирован: 08. Октября 2007
Re: Нужна помощь в оптимизации запроса на 1sqlite
Ответ #20 - 12. Апреля 2012 :: 09:24
Печать  
k_petrovich писал(а) 12. Апреля 2012 :: 08:22:
1SACCSEL пуста


ааа..значит снят отбор со счетов
  
Наверх
 
IP записан
 
Salimbek
God Member
*****
Отсутствует



Сообщений: 862
Зарегистрирован: 06. Июня 2006
Пол: Мужской
Re: Нужна помощь в оптимизации запроса на 1sqlite
Ответ #21 - 12. Апреля 2012 :: 13:50
Печать  
Что могу посоветовать:
1) Типизацию оставь только в первом запросе, остальные, подтянувшись через UNION, сами подтянуться
2) Если возможно, то вообще убери типизацию, лучше (например, для получения наименования) присоединить справочник "Номенклатура" к запросу и вытащить оттуда "Descr"
3) БухИтоги в 1С-ке вылизаны очень прилично, народ тестировал - существенного повышения производительности не получил (ну ты и сам видишь, глядя на OLEDB)
  
Наверх
ICQ  
IP записан
 
Переключение на Главную Страницу Страницы: [1] 
ОтправитьПечать