Переключение на Главную Страницу Страницы: [1] 2  ОтправитьПечать
Горячая тема (более 10 ответов) использование индекса для фильтра типа "кроме" (число прочтений - 3090 )
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 записан
 
Переключение на Главную Страницу Страницы: [1] 2 
ОтправитьПечать