Переключение на Главную Страницу Страницы: [1]  ОтправитьПечать
Горячая тема (более 10 ответов) использование индекса для фильтра типа "кроме" (число прочтений - 3157 )
ol
Senior Member
****
Отсутствует


1C++ rocks!

Сообщений: 272
Местоположение: Санкт-Петербург
Зарегистрирован: 24. Января 2009
Пол: Мужской
использование индекса для фильтра типа "кроме"
29. Апреля 2009 :: 11:19
Печать  
вот такой запрос (у измерения "Номенклатура" есть "Отбор итогов"):

Код
Выбрать все
select
$РегОстатки.Номенклатура Номенклатура,
$РегОстатки.Количество КоличествоОстаток
from $РегистрИтоги.ОстаткиТМЦ РегОстатки
inner join Номенклатура табНом on '20090101'+табНом.val=
	dtos(РегОстатки.period)+$РегОстатки.Номенклатура
 



индекс исправно работает.
а вот как использовать его, если требуется получить всю номенклатуру, кроме заданной в фильтре ?
  
Наверх
ICQ  
IP записан
 
ol
Senior Member
****
Отсутствует


1C++ rocks!

Сообщений: 272
Местоположение: Санкт-Петербург
Зарегистрирован: 24. Января 2009
Пол: Мужской
Re: использование индекса для фильтра типа "кроме"
Ответ #1 - 29. Апреля 2009 :: 11:39
Печать  
первое, что приходит в голову, запихать в этот фильтр всю номенклатуру "кроме"; но м. есть более изящное решение ?
  
Наверх
ICQ  
IP записан
 
Злой Бобр
Junior Member
**
Отсутствует



Сообщений: 56
Местоположение: Украина, Кривой Рог
Зарегистрирован: 07. Марта 2009
Пол: Мужской
Re: использование индекса для фильтра типа "кроме"
Ответ #2 - 29. Апреля 2009 :: 12:06
Печать  
WHERE $РегОстатки.Номенклатура NOT IN (SELECT Val FROM #ВыбНоменклатура)
Подмигивание
  

Если у вас есть деньги тогда мы идем к вам!!!
Наверх
ICQ  
IP записан
 
kiruha
1c++ power user
Отсутствует



Сообщений: 1249
Зарегистрирован: 11. Апреля 2007
Re: использование индекса для фильтра типа "кроме"
Ответ #3 - 29. Апреля 2009 :: 16:33
Печать  
Код
Выбрать все
select
$РегОстатки.Номенклатура Номенклатура,
$РегОстатки.Количество КоличествоОстаток
from $РегистрИтоги.ОстаткиТМЦ РегОстатки
WHERE dtos(РегОстатки.period)+$РегОстатки.Номенклатура LIKE '20090101'+'_________'
AND $РегОстатки.Номенклатура NOT IN (SELECT Val FROM #ВыбНоменклатура) 


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


1C++ rocks!

Сообщений: 272
Местоположение: Санкт-Петербург
Зарегистрирован: 24. Января 2009
Пол: Мужской
Re: использование индекса для фильтра типа "кроме"
Ответ #4 - 30. Апреля 2009 :: 05:41
Печать  
да, некоторое ускорение все таки при применении индекса есть, вот такие измерения на базе, размером примерно год (около 12 периодов)

Код
Выбрать все
select $РегОстатки.Номенклатура Номенклатура,$РегОстатки.Количество Количество
from $РегистрИтоги.ОстаткиТМЦ РегОстатки
where РегОстатки.period=:ДатаПериодаОстатков~~ and
$РегОстатки.Номенклатура not in (select табНом.val from Номенклатура табНом)

время запроса: 5118, строк: 57991
время запроса: 5065, строк: 57991
время запроса: 5154, строк: 57991
время запроса: 5168, строк: 57991
 



Код
Выбрать все
select $РегОстатки.Номенклатура Номенклатура,$РегОстатки.Количество Количество
from $РегистрИтоги.ОстаткиТМЦ РегОстатки
where
dtos(РегОстатки.period)+$РегОстатки.Номенклатура between '20090201' and '20090201ZZZZZZZZZ' and
$РегОстатки.Номенклатура not in (select табНом.val from Номенклатура табНом)

время запроса: 3676, строк: 57991
время запроса: 3677, строк: 57991
время запроса: 3627, строк: 57991
время запроса: 3851, строк: 57991
 




Код
Выбрать все
select $РегОстатки.Номенклатура Номенклатура,$РегОстатки.Количество Количество
from $РегистрИтоги.ОстаткиТМЦ РегОстатки
where
dtos(РегОстатки.period)+$РегОстатки.Номенклатура like '20090201_________'+'_________' and
$РегОстатки.Номенклатура not in (select табНом.val from Номенклатура табНом)

время запроса: 3688, строк: 57991
время запроса: 3710, строк: 57991
время запроса: 3716, строк: 57991
время запроса: 3735, строк: 57991
время запроса: 3762, строк: 57991
 


  
Наверх
ICQ  
IP записан
 
kiruha
1c++ power user
Отсутствует



Сообщений: 1249
Зарегистрирован: 11. Апреля 2007
Re: использование индекса для фильтра типа "кроме"
Ответ #5 - 30. Апреля 2009 :: 07:02
Печать  
Еще так можно попробовать
Код
Выбрать все
select
$РегОстатки.Номенклатура Номенклатура,
$РегОстатки.Количество КоличествоОстаток
from $РегистрИтоги.ОстаткиТМЦ РегОстатки
inner join
(Select $Спр.id as val2
FROM $Справочник.Номенклатура as Спр
Where
$Спр.id NOT IN (SELECT Val FROM #ВыбНоменклатура)
) табНом on '20090101'+табНом.val2=
	dtos(РегОстатки.period)+$РегОстатки.Номенклатура  
 


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


1C++ rocks!

Сообщений: 272
Местоположение: Санкт-Петербург
Зарегистрирован: 24. Января 2009
Пол: Мужской
Re: использование индекса для фильтра типа "кроме"
Ответ #6 - 30. Апреля 2009 :: 07:43
Печать  
это будет аналог того варианта, что "первый пришел в голову"  Улыбка
попробую, отпишусь о результате.
на первый взгляд, для тех баз, где в номенклатуре много позиций, не попадающих в регистр, будет проигрыш этого варианта
  
Наверх
ICQ  
IP записан
 
kiruha
1c++ power user
Отсутствует



Сообщений: 1249
Зарегистрирован: 11. Апреля 2007
Re: использование индекса для фильтра типа "кроме"
Ответ #7 - 30. Апреля 2009 :: 07:55
Печать  
ol писал(а) 30. Апреля 2009 :: 07:43:
это будет аналог того варианта, что "первый пришел в голову"  Улыбка
попробую, отпишусь о результате.
на первый взгляд, для тех баз, где в номенклатуре много позиций, не попадающих в регистр, будет проигрыш этого варианта


Да, мне тоже не нравится - даже если будет выигрыш в выбранной базе - в общем случае возможны тормоза
  
Наверх
 
IP записан
 
ol
Senior Member
****
Отсутствует


1C++ rocks!

Сообщений: 272
Местоположение: Санкт-Петербург
Зарегистрирован: 24. Января 2009
Пол: Мужской
Re: использование индекса для фильтра типа "кроме"
Ответ #8 - 30. Апреля 2009 :: 07:56
Печать  
мда, совсем чудеса пошли - результат запроса (количество строк) с этим вариантом другой

Код
Выбрать все
select $РегОстатки.Номенклатура Номенклатура,$РегОстатки.Количество Количество
from $РегистрИтоги.ОстаткиТМЦ РегОстатки
inner join
(Select Спр.id val2
FROM $Справочник.Номенклатура Спр
Where
Спр.id NOT IN (SELECT Val FROM #ВыбНоменклатура)
) табНом on '20071201'+табНом.val2=
	dtos(РегОстатки.period)+$РегОстатки.Номенклатура

время запроса: 3228, строк: 40958
 




Код
Выбрать все
select $РегОстатки.Номенклатура Номенклатура,$РегОстатки.Количество Количество
from $РегистрИтоги.ОстаткиТМЦ РегОстатки
where
dtos(РегОстатки.period)+$РегОстатки.Номенклатура like '20071201'+'_________'
and    
$РегОстатки.Номенклатура not in (select табНом.val from #ВыбНоменклатура табНом)
and $РегОстатки.Номенклатура<>$ПустойИд	    

время запроса: 3944, строк: 57991
 




поищу ка, где загвоздка
  
Наверх
ICQ  
IP записан
 
ol
Senior Member
****
Отсутствует


1C++ rocks!

Сообщений: 272
Местоположение: Санкт-Петербург
Зарегистрирован: 24. Января 2009
Пол: Мужской
Re: использование индекса для фильтра типа "кроме"
Ответ #9 - 30. Апреля 2009 :: 08:22
Печать  
ага, разобрался, если добавить

having $РегОстатки.Количество<>0
то количество строк будет одинаковым.

в итоге вариант

Код
Выбрать все
inner join
(Select Спр.id val2
FROM $Справочник.Номенклатура Спр
Where
Спр.id NOT IN (SELECT Val FROM #ВыбНоменклатура)
) табНом on '20071201'+табНом.val2=
	dtos(РегОстатки.period)+$РегОстатки.Номенклатура
 



отрабатывал примерно то же время, или чуть медленнее, нежели

Код
Выбрать все
where
dtos(РегОстатки.period)+$РегОстатки.Номенклатура like '20071201'+'_________' and
$РегОстатки.Номенклатура not in (select табНом.val from #ВыбНоменклатура табНом)
 

  
Наверх
ICQ  
IP записан
 
ol
Senior Member
****
Отсутствует


1C++ rocks!

Сообщений: 272
Местоположение: Санкт-Петербург
Зарегистрирован: 24. Января 2009
Пол: Мужской
Re: использование индекса для фильтра типа "кроме"
Ответ #10 - 30. Апреля 2009 :: 08:36
Печать  
хотя, если запихать в фильтр почти весь справочник, вариант

...
inner join
(Select Спр.id val2
FROM $Справочник.Номенклатура Спр
Where ...


несколько выигрывает; не настолько, конечно, чтобы из за этого наворачивать код.

kiruha, спасибо за идеи  Улыбка
  
Наверх
ICQ  
IP записан
 
Z1
God Member
*****
Отсутствует


I Love YaBB 2!

Сообщений: 2906
Местоположение: Москва
Зарегистрирован: 26. Мая 2006
Пол: Мужской
Re: использование индекса для фильтра типа "кроме"
Ответ #11 - 30. Апреля 2009 :: 08:39
Печать  
как правило в дереве товаров листья лежат только на конечном уровне и запросы формулируются в рамках папок.
Тогда если вышеназванные условия выполняются запросы надо переделывать на папки. Т.к. папок гораздо меньше чем
элементов то сразу и увидишь выигрыш.
Другой вариант искать специфику твоих данных товаров и стараться ее использовать в запросах.
  
Наверх
 
IP записан
 
ol
Senior Member
****
Отсутствует


1C++ rocks!

Сообщений: 272
Местоположение: Санкт-Петербург
Зарегистрирован: 24. Января 2009
Пол: Мужской
Re: использование индекса для фильтра типа "кроме"
Ответ #12 - 30. Апреля 2009 :: 08:47
Печать  
(12)
под конкретную задачу, скорее всего можно оптимизировать. в данном случае я пытался понять, как действовать в общем случае, т.е. написать универсальный код, который будет как можно меньше проигрывать адаптированному к некой базе
  
Наверх
ICQ  
IP записан
 
Z1
God Member
*****
Отсутствует


I Love YaBB 2!

Сообщений: 2906
Местоположение: Москва
Зарегистрирован: 26. Мая 2006
Пол: Мужской
Re: использование индекса для фильтра типа "кроме"
Ответ #13 - 30. Апреля 2009 :: 08:57
Печать  
ol писал(а) 30. Апреля 2009 :: 08:47:
(12)
под конкретную задачу, скорее всего можно оптимизировать. в данном случае я пытался понять, как действовать в общем случае, т.е. написать универсальный код, который будет как можно меньше проигрывать адаптированному к некой базе

чем более универсальный код тем больше он проигрывает частным случаю и наоборот.
Пример запрос 1с - более универсален чем прямой запрос
и при этом запрос 1с более медленный чем прямой запрос.
  
Наверх
 
IP записан
 
ol
Senior Member
****
Отсутствует


1C++ rocks!

Сообщений: 272
Местоположение: Санкт-Петербург
Зарегистрирован: 24. Января 2009
Пол: Мужской
Re: использование индекса для фильтра типа "кроме"
Ответ #14 - 30. Апреля 2009 :: 09:12
Печать  
по поводу проигрыша запроса 1с - игра стоит свеч, то есть есть смысл попариться с кодом, чтобы выиграть по скорости раз в 50  Улыбка

но наворачивать код ради выигрыша в 10% как то стремно.

вот проверил еще такой вариант:

Код
Выбрать все
select $РегОстатки.Номенклатура Номенклатура,$РегОстатки.Количество Количество
from $РегистрИтоги.ОстаткиТМЦ РегОстатки
inner join
(Select Спр0.id val2
FROM $Справочник.Номенклатура Спр0
Where
(Спр0.parentid<>:ВыбТМЦ)
) табНом on '20071201'+табНом.val2=
	dtos(РегОстатки.period)+$РегОстатки.Номенклатура
having $РегОстатки.Количество<>0
 



правда в данном случае, я знаю, что в группе ВыбТМЦ нет вложенных групп, в противном случае запрос еще несколько усложняется.

выполняется он примерно то же время, что и предыдущие лучшие варианты. Экономия здесь возможна на
УложитьСписокОбъектов(ВыбТМЦ,....)
  
Наверх
ICQ  
IP записан
 
ol
Senior Member
****
Отсутствует


1C++ rocks!

Сообщений: 272
Местоположение: Санкт-Петербург
Зарегистрирован: 24. Января 2009
Пол: Мужской
Re: использование индекса для фильтра типа "кроме"
Ответ #15 - 30. Апреля 2009 :: 09:15
Печать  
кстати! по поводу универсальности запроса 1с - я бы сказал, что он предполагает меньше возможностей. то бишь, где можно при помощи прямого запроса получить сразу готовый массив, запрос 1с еще надо будет подработать напильничком
  
Наверх
ICQ  
IP записан
 
Переключение на Главную Страницу Страницы: [1] 
ОтправитьПечать