Переключение на Главную Страницу Страницы: [1] 2 3  ОтправитьПечать
Очень популярная тема (более 25 ответов) Медленное получение значения периодического реквизита (число прочтений - 10513 )
Neo
Senior Member
****
Отсутствует


I Love YaBB 2!

Сообщений: 327
Зарегистрирован: 12. Ноября 2007
Медленное получение значения периодического реквизита
07. Декабря 2009 :: 09:55
Печать  
Сравниваю производительность одинаковых баз на двух разных серваках. Один сервак гораздо более мощный (и дисковая подсистема, и оперативная память, и проц). И практически на всех операторах это заметно: быстрее выполняются запросы, быстрее выводятся результаты запроса в отчет и т.п.

Единственно, что никак не могу понять, так это то, что на более мощном серваке дико тормозит оператор получения периодического реквизита, типа Валюта.Курс.Получить(Дата).

Например, в одном коде перебираются даты за несколько месяцев и на каждый день выполянется расчет курса и все это загоняется в ТЗ.

Так вот на 300 вызовах на более мощном сервере наблюдается общее замедление в 24 раза. Из-за чего такое может быть?
  
Наверх
 
IP записан
 
Neo
Senior Member
****
Отсутствует


I Love YaBB 2!

Сообщений: 327
Зарегистрирован: 12. Ноября 2007
Re: Медленное получение значения периодического реквизита
Ответ #1 - 07. Декабря 2009 :: 09:56
Печать  
Ну и соотвественно хотелось бы это как-то ускорить.
Но в первую очередь  определить причины нынешней ситуации
  
Наверх
 
IP записан
 
trad
1c++ power user
1c++ donor
1c++ moderator
Отсутствует



Сообщений: 3051
Местоположение: Киров
Зарегистрирован: 23. Мая 2006
Пол: Мужской
Re: Медленное получение значения периодического реквизита
Ответ #2 - 07. Декабря 2009 :: 10:05
Печать  
попробуй переиндексировать _1sconst
  

1&&2&&3
Наверх
 
IP записан
 
Злоп
Senior Member
****
Отсутствует


Ябба!

Сообщений: 317
Местоположение: г.Москва
Зарегистрирован: 14. Августа 2006
Пол: Мужской
Re: Медленное получение значения периодического реквизита
Ответ #3 - 07. Декабря 2009 :: 23:34
Печать  
Если пользоваться штатными возможностями, то использование для доступа к периодическим згначениям через
Пер = СоздатьОбъект("Периодический") - позволяет добиться ускорения примерно 25%
  
Наверх
www  
IP записан
 
Z1
God Member
*****
Отсутствует


I Love YaBB 2!

Сообщений: 2906
Местоположение: Москва
Зарегистрирован: 26. Мая 2006
Пол: Мужской
Re: Медленное получение значения периодического реквизита
Ответ #4 - 09. Декабря 2009 :: 07:29
Печать  
Neo писал(а) 07. Декабря 2009 :: 09:55:
Сравниваю производительность одинаковых баз на двух разных серваках. Один сервак гораздо более мощный (и дисковая подсистема, и оперативная память, и проц). И практически на всех операторах это заметно: быстрее выполняются запросы, быстрее выводятся результаты запроса в отчет и т.п.

Единственно, что никак не могу понять, так это то, что на более мощном серваке дико тормозит оператор получения периодического реквизита, типа Валюта.Курс.Получить(Дата).

Например, в одном коде перебираются даты за несколько месяцев и на каждый день выполянется расчет курса и все это загоняется в ТЗ.

Так вот на 300 вызовах на более мощном сервере наблюдается общее замедление в 24 раза. Из-за чего такое может быть?

Приведи более конкретный пример.
Я всегда использую ИспользоватьДату()
Кстати не рекомендуется смешивать Получить и использоватьДату.
Может быть у тебя именно этот случай?
  
Наверх
 
IP записан
 
elkpro
Full Member
***
Отсутствует


I Love YaBB 2!

Сообщений: 145
Зарегистрирован: 19. Мая 2006
Re: Медленное получение значения периодического реквизита
Ответ #5 - 09. Декабря 2009 :: 15:39
Печать  
У нас на базе зачастую наблюдается торможение при обращении к курсу валюты.

Через профайлер видно, что выполняется такой запрос
exec sp_executesql N'Select * from _1SCONST(NOLOCK) where ID=@P1 and OBJID=@P2 and DATE<=@P3 order by ID DESC, OBJID DESC, DATE DESC, TIME DESC, DOCID DESC, N'@P1 int,@P2 varchar(9),@P3 datetime', 92, '     2   ', 'Dec  9 2009 12:00:00:000AM'
и генерирует READS - 69993 и DURATION - 593
что видно, что зашкаливает.

Посмотрев план запроса - можно увидеть, что он сканирует таблицу констант и вытаскивает оттуда порядка 2800 строк.
Реиндексация не помогала. Помогло обновление статистики. Сейчас у меня статистика обновляется каждый день, т.к. размер базы уже порядка 65 Gb. В справочнике _1sconst сейчас порядка 2 200 000 записей.
  
Наверх
 
IP записан
 
Z1
God Member
*****
Отсутствует


I Love YaBB 2!

Сообщений: 2906
Местоположение: Москва
Зарегистрирован: 26. Мая 2006
Пол: Мужской
Re: Медленное получение значения периодического реквизита
Ответ #6 - 10. Декабря 2009 :: 06:58
Печать  
Только что проверил три разных метода
Код
Выбрать все
Процедура Сформировать1()
	Спр1 = СоздатьОбъект("Справочник.Валюты");
	Спр1.ИспользоватьДату(Дата1);
	Спр1.НайтиЭлемент(Вал1);
	Зн1 = Спр1.Текущ_курс;
	Сообщить("метод1 на дату = " + Дата1 + " курс = " + Зн1);
КонецПроцедуры

Процедура Сформировать2()
	Спр1 = СоздатьОбъект("Справочник.Валюты");
	Спр1.НайтиЭлемент(Вал1);
	Зн1 = Спр1.Текущ_курс.Получить(Дата1);
	Сообщить("метод2 на дату = " + Дата1 + " курс = " + Зн1);
КонецПроцедуры

Процедура Сформировать3()
	Спр1 = СоздатьОбъект("Справочник.Валюты");
	Спр1.НайтиЭлемент(Вал1);
	ТекЗапись=Спр1.ТекущийЭлемент();
	ПерКурс=СоздатьОбъект("Периодический");
	ПерКурс.ИспользоватьОбъект("Текущ_курс",ТекЗапись);
	Зн1 = ПерКурс.ЗначениеНаДату(Дата1);
	Сообщить("метод3 на дату = " + Дата1 + " курс = " + Зн1);
КонецПроцедуры
 


Все генерируют один и тот же запрос к базе данных

Код
Выбрать все
exec sp_executesql N'Select * from _1SCONST(NOLOCK)
where ID=@P1 and OBJID=@P2 and DATE<=@P3
order by ID DESC, OBJID DESC, DATE DESC, TIME DESC, DOCID DESC'
, N'@P1 int,@P2 varchar(9),@P3 datetime', 92, '     2   ', 'Oct  1 2009 12:00:00:000AM'
 


Недостатки этого запроса
1. Зачем возвращать все значения( а если там миллион строк) меня интересует только самая последняя  дата ( первая в выборке) надо всего лишь поставить  top 1
2. Зачем нужны order by ID DESC, OBJID DESC ведь id OBJID
не изменяются - лишняя нагрузка на sql
3. Если значения не меняются документами  тогда достаточно будет только сортировки  DATE

Вывод Чтобы ускорить получение периодич значения на дату
надо написать свой прямой запрос.

Если значение не меняется документами :
Select top 1 * from _1SCONST(NOLOCK)
where ID=@P1 and OBJID=@P2 and DATE<=@P3
order by DATE DESC


Если значение  меняется документами :
Select top 1 * from _1SCONST(NOLOCK)
where ID=@P1 and OBJID=@P2 and DATE<=@P3
order by DATE DESC, TIME DESC, DOCID DESC


Еще больше ускорить можно если эти новые запросы оформить как хранимые процедуры.

  
Наверх
 
IP записан
 
elkpro
Full Member
***
Отсутствует


I Love YaBB 2!

Сообщений: 145
Зарегистрирован: 19. Мая 2006
Re: Медленное получение значения периодического реквизита
Ответ #7 - 10. Декабря 2009 :: 07:11
Печать  
По поводу сортировки - ты не прав. 1С использует правильную конструкцию, т.к. только в этом случае идет точное попадание в индекс IDD
#----Indexes------
# Name                           |Descr         |Unique|Indexed fields                                              |Type      
I=PK__1SCONST                    |              |1     |ROW_ID                                                      |1         
I=IDD                            |              |1     |ID,OBJID,DATE,TIME,DOCID,ROW_ID                             |0         
I=DOC                            |              |1     |DOCID,ACTNO,ROW_ID                                          |0   


Я в базе переделал стандартную функцию получения курсов валют через параметрезированный запрос и  убрал в программе везде обращения напрямую типа Валюта.Курс.Получить() на глПолучитьКурс(Валюта,Дата). Это решило данную проблему и скорость существенно возросла.
У нас комплексная база и документ переоценка валют проводился порядка 40 мин. После вышеупомянутой замены стал проводится 5 мин.
Но таким образом нельзя решить проблему в Операциях, когда 1С каким-то своим способом обращается к константам для обновления текущего курса валюты в проводках.
  
Наверх
 
IP записан
 
Z1
God Member
*****
Отсутствует


I Love YaBB 2!

Сообщений: 2906
Местоположение: Москва
Зарегистрирован: 26. Мая 2006
Пол: Мужской
Re: Медленное получение значения периодического реквизита
Ответ #8 - 10. Декабря 2009 :: 07:17
Печать  
elkpro писал(а) 10. Декабря 2009 :: 07:11:
По поводу сортировки - ты не прав. 1С использует правильную конструкцию, т.к. только в этом случае идет точное попадание в индекс IDD
#----Indexes------
# Name                           |Descr         |Unique|Indexed fields                                              |Type      
I=PK__1SCONST                    |              |1     |ROW_ID                                                      |1          
I=IDD                            |              |1     |ID,OBJID,DATE,TIME,DOCID,ROW_ID                             |0          
I=DOC                            |              |1     |DOCID,ACTNO,ROW_ID                                          |0  


Я в базе переделал стандартную функцию получения курсов валют через параметрезированный запрос и  убрал в программе везде обращения напрямую типа Валюта.Курс.Получить() на глПолучитьКурс(Валюта,Дата). Это решило данную проблему и скорость существенно возросла.
У нас комплексная база и документ переоценка валют проводился порядка 40 мин. После вышеупомянутой замены стал проводится 5 мин.
Но таким образом нельзя решить проблему в Операциях, когда 1С каким-то своим способом обращается к константам для обновления текущего курса валюты в проводках.

И в чем я не прав. Индекс sql и сам подберет какой нужно ( а
если надо можно и самому его указать индекс) а дальше при сортировке
либо sql сервер будет делать не думая и сортировать все заданные поля
либо проанализировав ситуацию отбросит первые лишние сортировки,
но все равно sql сервер на это потратит свое время.
  
Наверх
 
IP записан
 
berezdetsky
1c++ power user
Отсутствует


barba non facit sisadminum

Сообщений: 1986
Местоположение: Москва
Зарегистрирован: 19. Мая 2006
Пол: Мужской
Re: Медленное получение значения периодического реквизита
Ответ #9 - 10. Декабря 2009 :: 07:42
Печать  
При попадании в индекс сортировки просто не будет.
  

пароль как коньяк, чем больше звездочек, тем лучше
Наверх
IP записан
 
elkpro
Full Member
***
Отсутствует


I Love YaBB 2!

Сообщений: 145
Зарегистрирован: 19. Мая 2006
Re: Медленное получение значения периодического реквизита
Ответ #10 - 10. Декабря 2009 :: 07:42
Печать  
Нет в таблице индекса для поля DATE, которое сервер бы взял и использовал.
При этом при выполнении запроса не тратится время на нахождение данных в индексе, а потом на сортировку данных в таблице. SQL это сделает за один проход, т.к. в индексе перечислены все поля и эти данные он вытащит из индекса без обращений к таблице в уже упорядоченном варианте как указано в запросе.
Чего рассказывать теорию, когда ты это можешь взять и проверить на практике и посмотри что покажет план исполнения.
Сейчас при тормозном варианте используется Clustered Index Scan. В идеале должен использовать Index Seek  - idd.


  
Наверх
 
IP записан
 
Z1
God Member
*****
Отсутствует


I Love YaBB 2!

Сообщений: 2906
Местоположение: Москва
Зарегистрирован: 26. Мая 2006
Пол: Мужской
Re: Медленное получение значения периодического реквизита
Ответ #11 - 10. Декабря 2009 :: 08:03
Печать  
Что выберет sql еще зависит и от данных и от статистики
только что проверил

Select * from _1SCONST(NOLOCK)
where ID=92 and OBJID='     2   '
and DATE<='Oct  1 2009 12:00:00:000AM'
order by ID DESC, OBJID DESC, DATE DESC, TIME DESC, DOCID DESC


Select * from _1SCONST(NOLOCK)
where ID=92 and OBJID='     2   '
and DATE<='Oct  1 2009 12:00:00:000AM'
order by DATE DESC

Для обоих запросов sql выбрал cluster index scan ( строк в выборке 163 )
  
Наверх
 
IP записан
 
elkpro
Full Member
***
Отсутствует


I Love YaBB 2!

Сообщений: 145
Зарегистрирован: 19. Мая 2006
Re: Медленное получение значения периодического реквизита
Ответ #12 - 10. Декабря 2009 :: 08:19
Печать  
Я про индексирование и статистику уже писал.
В моем случае, когда вытаскиваются периодические значения на Май 2008, то он всегда использует Clustered Index Scan. Если я меняю дату на текущее число - тогда использует Index Seek - IDD.
  
Наверх
 
IP записан
 
elkpro
Full Member
***
Отсутствует


I Love YaBB 2!

Сообщений: 145
Зарегистрирован: 19. Мая 2006
Re: Медленное получение значения периодического реквизита
Ответ #13 - 10. Декабря 2009 :: 08:23
Печать  
У меня собственно сделан такой запрос

Это при загрузке 1С
ТекстЗапроса="
     |DECLARE @пВалюта char(9), @пНаДату datetime
     |SET @пНаДату = ?
     |SET @пВалюта = ?
     |SELECT CASE WHEN Кратность=0 THEN Курс ELSE Курс/Кратность END Курс
     |FROM (
     |SELECT $ПоследнееЗначение.Валюты.Курс(@пВалюта,@пНаДату) Курс
     |       , COALESCE($ПоследнееЗначение.Валюты.Кратность(@пВалюта,@пНаДату),1) Кратность ) Курсы
     |";
     
     глЗапросПоВалютам=СоздатьОбъект("ODBCRecordSet");
     глЗапросПоВалютам.Подготовить(ТекстЗапроса);
     глЗапросПоВалютам.ДобПараметр(1,10,17,0);
     глЗапросПоВалютам.ДобПараметр(1,14,9,0);


Функция глКурсДляВалюты(Валюта,ДатаКурса) Экспорт
     
     Если ПустоеЗначение(ДатаКурса)=1 Тогда
           ДатаКурса=РабочаяДата();
     КонецЕсли;      
     
     Если ТипЗначенияСтр(ДатаКурса)="Документ" Тогда
           ДатаКурса=ДатаКурса.ДатаДок;
-- не вытаскивает курс на документ, т.к. у меня параметр типа дата
     КонецЕсли;      

     глЗапросПоВалютам.УстПараметр(1,ДатаКурса);
     
     Если Валюта=Рубли Тогда
           // Для базовой валюты курс всегда равен 1, поэтому отображаем курс Основной валюты
           глЗапросПоВалютам.УстПараметр(2,Константа.ОсновнаяВалюта);
     Иначе    // для других валют записываем их собственный курс
           глЗапросПоВалютам.УстПараметр(2,Валюта);
     КонецЕсли;
     
     Возврат глЗапросПоВалютам.ВыполнитьСкалярный();
     
КонецФункции
  
Наверх
 
IP записан
 
Z1
God Member
*****
Отсутствует


I Love YaBB 2!

Сообщений: 2906
Местоположение: Москва
Зарегистрирован: 26. Мая 2006
Пол: Мужской
Re: Медленное получение значения периодического реквизита
Ответ #14 - 10. Декабря 2009 :: 08:27
Печать  
Если же поставить top 1

Select top 1 * from _1SCONST(NOLOCK)
where ID=92 and OBJID='     2   '
and DATE<='Oct  1 2009 12:00:00:000AM'
order by ID DESC, OBJID DESC, DATE DESC, TIME DESC, DOCID DESC


Select top 1 * from _1SCONST(NOLOCK)
where ID=92 and OBJID='     2   '
and DATE<='Oct  1 2009 12:00:00:000AM'
order by DATE DESC

Для обоих запросов sql выбрал index seek  IDD
при этом  стоимость стала 3 вместо 0 при scan cluster index
  
Наверх
 
IP записан
 
Переключение на Главную Страницу Страницы: [1] 2 3 
ОтправитьПечать