Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
 INTERSECT slow  [new]
handmadeFromRu
Member

Откуда: родина Ленина!
Сообщений: 1980
задача найти пересечение множеств по сути. INTERSECT сразу же в голову приходит. Но тут встает одно "но" если ищу где то пересечение между 5 и более множествами, а конкретно 10-ю, вижу задержку в 2 секунды. Просто селекты без операции пересечения мгновенны. Неужели операция такая тяжелая? И как можно обойтись без INTERSECT. Если кто то может что то посоветовать буду благодарен, если не хватает структуры таблиц могу и их привести.
17 ноя 12, 16:55    [13488792]     Ответить | Цитировать Сообщить модератору
 Re: INTERSECT slow  [new]
aleks2
Guest
1. Ваще то, intersect делается через простой inner join.
2. Ну и join 10 таблиц никогда лехкой операцией не был.
3. Временные таблицы спасут отца русской дерьмократии.
17 ноя 12, 17:11    [13488822]     Ответить | Цитировать Сообщить модератору
 Re: INTERSECT slow  [new]
SomewhereSomehow
Member

Откуда: Moscow
Сообщений: 2480
Блог
handmadeFromRu,

Нужно смотреть на планы выполнения, смотря что у вас за таблицы и что происходит там...
17 ноя 12, 17:13    [13488824]     Ответить | Цитировать Сообщить модератору
 Re: INTERSECT slow  [new]
handmadeFromRu
Member

Откуда: родина Ленина!
Сообщений: 1980
ну вообщем такая структура таблиц
есть таблица группы свойств
 TABLE [dbo].[FilterCategory](
	[Id] [int] IDENTITY(1,1) NOT NULL,
	[Name] [nvarchar](250) NOT NULL,
	[ParentId] [int] NULL,

есть таблица собственно самих значений
 TABLE [dbo].[FilterValue](
	[Id] [int] IDENTITY(1,1) NOT NULL,
	[ParentId] [int] NOT NULL,
	[Value] [nvarchar](250) NULL,

и есть таблица
TABLE [dbo].[FilterValueLinked](
	[MainValueId] [int] NOT NULL,
	[LinkedValueId] [int] NOT NULL,

где хранятся связанные айдишники значений., почему именно так сделал поясню: на входе системе приходят строки из экселя или csv. пример 9 | white| xxl | silk| и т.д. где 9 это номер товара в бд, а другие столбцы характеристики этого товара, по сути каждая характеристика это категория фильтра. FilterValueLinked мапинг значений свойств между друг другом в 1 строке. Так вот INTERSECT нужен чтоб чтобы урезать запрос каждый раз, по сути уточнять

Сам запрос:
select * from dbo.FilterValue where Id in (
Select MainValueId from dbo.FilterValueLinked where LinkedValueId = 5
INTERSECT
Select MainValueId from dbo.FilterValueLinked where LinkedValueId =6
INTERSECT
Select MainValueId from dbo.FilterValueLinked where LinkedValueId  =7
INTERSECT
Select MainValueId from dbo.FilterValueLinked where LinkedValueId  =8
INTERSECT 
Select MainValueId from dbo.FilterValueLinked where LinkedValueId =9
INTERSECT 
Select MainValueId from dbo.FilterValueLinked where LinkedValueId  = 10
INTERSECT
Select MainValueId from dbo.FilterValueLinked where LinkedValueId  =11
INTERSECT 
Select MainValueId from dbo.FilterValueLinked where LinkedValueId  =12
INTERSECT 
Select MainValueId from dbo.FilterValueLinked where LinkedValueId  =13
) and ParentId=10 order by SortOrder

2aleks2
вы имеет ввиду CTE? или создание таблиц на лету, что вообще убьет перфоманс
17 ноя 12, 17:37    [13488886]     Ответить | Цитировать Сообщить модератору
 Re: INTERSECT slow  [new]
aleks2
Guest
Грамотей. Это сделает твово монстрека.
declare @t1 table(MainValueId int primary key clustered)
insert @t1
Select MainValueId from dbo.FilterValueLinked where LinkedValueId = 5
INTERSECT
Select MainValueId from dbo.FilterValueLinked where LinkedValueId =6

declare @t2 table(MainValueId int primary key clustered)
insert @t2
Select MainValueId from @t1
INTERSECT
Select MainValueId from dbo.FilterValueLinked where LinkedValueId =7

declare @t3 table(MainValueId int primary key clustered)
insert @t3
Select MainValueId from @t2
INTERSECT
Select MainValueId from dbo.FilterValueLinked where LinkedValueId =8

...

select * from dbo.FilterValue 
where Id in (Select MainValueId from @t8)
  and ParentId=10 order by SortOrder
17 ноя 12, 18:46    [13489035]     Ответить | Цитировать Сообщить модератору
 Re: INTERSECT slow  [new]
iap
Member

Откуда: Москва
Сообщений: 47001
handmadeFromRu,

какие индексы есть?
17 ноя 12, 19:34    [13489132]     Ответить | Цитировать Сообщить модератору
 Re: INTERSECT slow  [new]
handmadeFromRu
Member

Откуда: родина Ленина!
Сообщений: 1980
2aleks2
вариант работает шикарно, но трабл в том что я не смогу это заюзать. У меня количество операций INTERSECT переменное, соответственно я строю запрос ручками в коде, а насколько я помню не получиться создавать переменные если в коде я помечу CommanType.Text

2iap
FilterCategory кластерный Id некластерный ParentId
FilterValue кластерный Id некластерный ParentId
FilterValueLinked кластерный MainValueId некластерный LinkedValueId
17 ноя 12, 19:56    [13489162]     Ответить | Цитировать Сообщить модератору
 Re: INTERSECT slow  [new]
SomewhereSomehow
Member

Откуда: Moscow
Сообщений: 2480
Блог
handmadeFromRu
2aleks2
вариант работает шикарно, но трабл в том что я не смогу это заюзать. У меня количество операций INTERSECT переменное

Ну и планы стало быть тоже переменные. А нужно говорить о чем-то конкретном.

Но вообще, сама форма запроса немного настораживает, есть такой совет в правилах форума, озвучивать задачу в целом, я думаю, это как раз тот случай. Может быть, вы скажете что вы имеете - и что надо получить, а вам предложат альтернативное решение...
17 ноя 12, 20:07    [13489180]     Ответить | Цитировать Сообщить модератору
 Re: INTERSECT slow  [new]
invm
Member

Откуда: Москва
Сообщений: 9406
create type dbo.ttLinkedValueIds as table
(
 LinkedValueId int not null primary key
);
go

create procedure dbo.spGetFilterValues
	@l dbo.ttLinkedValueIds readonly
as
begin
 set nocount on;
 
 declare @t table (MainValueId int not null);
 
 insert into @t
 select
  fvl.MainValueId
 from
  @l l join
  dbo.FilterValueLinked fvl on fvl.LinkedValueId = l.LinkedValueId
 group by
  fvl.MainValueId
 having
  count(distinct fvl.LinkedValueId) = (select count(*) from @l);
  
 select
  fv.*
 from
  @t t join
  dbo.FilterValue fv on fv.MainValueId = t.MainValueId and fv.ParentId = 10
 order by
  fv.SortOrder;
  
end;
go
17 ноя 12, 20:14    [13489196]     Ответить | Цитировать Сообщить модератору
 Re: INTERSECT slow  [new]
handmadeFromRu
Member

Откуда: родина Ленина!
Сообщений: 1980
SomewhereSomehow
Ну и планы стало быть тоже переменные. А нужно говорить о чем-то конкретном.

Но вообще, сама форма запроса немного настораживает, есть такой совет в правилах форума, озвучивать задачу в целом, я думаю, это как раз тот случай. Может быть, вы скажете что вы имеете - и что надо получить, а вам предложат альтернативное решение...

я чуть выше, где описывал таблицы, рассказал что и где лежит, пример из 10 INTERSECT самый плохой вариант в моем случае т.е. больше не будет, а вот с 1 - 10 вхождений легко. Могу дописать, если не правильно выразился где-то.
17 ноя 12, 20:26    [13489244]     Ответить | Цитировать Сообщить модератору
 Re: INTERSECT slow  [new]
handmadeFromRu
Member

Откуда: родина Ленина!
Сообщений: 1980
invm,

а как этим пользоваться? я свои типы данных не пробывал делать
17 ноя 12, 20:43    [13489311]     Ответить | Цитировать Сообщить модератору
 Re: INTERSECT slow  [new]
invm
Member

Откуда: Москва
Сообщений: 9406
handmadeFromRu
а как этим пользоваться? я свои типы данных не пробывал делать
http://www.codeproject.com/Articles/39161/C-and-Table-Value-Parameters
17 ноя 12, 21:03    [13489382]     Ответить | Цитировать Сообщить модератору
 Re: INTERSECT slow  [new]
handmadeFromRu
Member

Откуда: родина Ленина!
Сообщений: 1980
спасибо. буду пробывать
17 ноя 12, 21:08    [13489400]     Ответить | Цитировать Сообщить модератору
 Re: INTERSECT slow  [new]
SomewhereSomehow
Member

Откуда: Moscow
Сообщений: 2480
Блог
handmadeFromRu,

intersect сама по себе операция не дешевая. Там могут быть задействованы, все красавцы типа "aggregate","distinct sort" и т.д.
Возможно, всего этого и не будет, но - неизвестно, какие у вас таблицы и индексы. Я спрашивал об этом.
Также этот вопрос, вам уже задал iap, еще в начале обсуждения.

Если же вы меняете запрос, условия, количество таблиц - то не имеет смысла говорить о чем-то общем. Если вы вытаскиваете из базы какие-то данные и смотрите две таблицы, но вытаскиваете похожие данные и смотрите уже четыре - это....ну на мой взгляд свидетельствует о плохой архитектуре.

Тут, имхо, один совет: соблюдайте реляционную модель

Пространно рассуждать можно много, все-таки, логичекая задача облегчила бы понимание =)
17 ноя 12, 21:16    [13489431]     Ответить | Цитировать Сообщить модератору
 Re: INTERSECT slow  [new]
handmadeFromRu
Member

Откуда: родина Ленина!
Сообщений: 1980
вариант invm мне подошел идеально.
ну смотрите...я описал 3 таблицы вверху.2 таблицы а именно категории и значения все просто. 3 таблица служит служебной, чисто чтоб связать свойства друг с другом что это значит. к примеру из вне мне приходят данные
productId Color Size Material и т.д.
1 черный 46 хлопок
1 красный 47 хлопок
1 белый 48 хлопок
и т.д.
как видно у товара 1 3 набора свойств.
у 1 товара может быть разное кол-во наборов свойств + источников данных несколько и кол-во свойств от них разное поступает, кто то возвращает 10 свойств , кто то всего 6.
из-за этого я ввел таблицу FilterValueLinked. Я там собственно линкую между собой все свойства в строке приходящих данных + линкую каждое отдельное свойство с товаром, но в запросе это не участвует для урезания фильтра. По другому не знаю как запроектировать, вроде логично все. Поправьте меня если не так, буду признателен
17 ноя 12, 21:28    [13489478]     Ответить | Цитировать Сообщить модератору
 Re: INTERSECT slow  [new]
aleks2
Guest
handmadeFromRu
2aleks2
вариант работает шикарно, но трабл в том что я не смогу это заюзать. У меня количество операций INTERSECT переменное, соответственно я строю запрос ручками в коде, а насколько я помню не получиться создавать переменные если в коде я помечу CommanType.Text


Чему нынче программистов учат?
declare @l table(LinkedValueId int primary key clustered);

insert @l
values (5),(6),(7),(8),(9),(10);

declare @l1 int, @l2 int;

declare @t table(MainValueId int primary key clustered);


set @l1 = ( select MIN(LinkedValueId) from @l );
set @l2 = ( select MIN(LinkedValueId) from @l where LinkedValueId > @l1);

insert @t
Select MainValueId from dbo.FilterValueLinked where LinkedValueId = @l1
INTERSECT
Select MainValueId from dbo.FilterValueLinked where LinkedValueId = @l2;

set @l1 = ( select MIN(LinkedValueId) from @l where LinkedValueId > @l2 );

while @l1 is not null
begin
  delete T
  from @t T 
  where T.MainValueId not in 
   (
    Select MainValueId from dbo.FilterValueLinked where LinkedValueId = @l1
    INTERSECT
    Select MainValueId from @t
    );

  set @l1 = ( select MIN(LinkedValueId) from @l where LinkedValueId > @l1 );
end;

select * from dbo.FilterValue 
where Id in (Select MainValueId from @t)
  and ParentId=10 order by SortOrder
18 ноя 12, 11:07    [13490365]     Ответить | Цитировать Сообщить модератору
 Re: INTERSECT slow  [new]
handmadeFromRu
Member

Откуда: родина Ленина!
Сообщений: 1980
aleks2
Чему нынче программистов учат?

ну что сказать...спасибо!
18 ноя 12, 16:59    [13490862]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить