Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
Топик располагается на нескольких страницах: [1] 2   вперед  Ctrl      все
 оптимизация запроса (много раз between) ms sql 2005  [new]
trew
Member

Откуда: Москва
Сообщений: 2646
DECLARE @tab table 
	(id int unique
	,date1 smalldatetime
	,date2 smalldatetime
	,date3 smalldatetime
	,date4 smalldatetime
	,date5 smalldatetime
	)
			
INSERT INTO @tab (id, date1, date2, date3, date4, date5)
SELECT 1, '20120625', '20120613', null, '20120608', '20120602'	
UNION ALL
SELECT 2, '20120730', '20120713', '20120714', '20120708', null
UNION ALL
SELECT 3, '20120718', null, '20120717', '20120614', '20120615'
UNION ALL
SELECT 4, '20120615', null, null, null, null

-- SELECT * FROM @tab

DECLARE @date_begin smalldatetime
DECLARE @date_end smalldatetime

SELECT @date_begin ='20120608', @date_end ='20120707'

SELECT * FROM @tab
WHERE date1 BETWEEN @date_begin AND @date_end
-- date1 >= @date_begin AND date1 <= @date_end
OR date2 BETWEEN @date_begin AND @date_end
OR date3 BETWEEN @date_begin AND @date_end
OR date4 BETWEEN @date_begin AND @date_end
OR date5 BETWEEN @date_begin AND @date_end

Как ускорить работу последнего запроса?
20 июл 12, 13:43    [12893230]     Ответить | Цитировать Сообщить модератору
 Re: оптимизация запроса (много раз between) ms sql 2005  [new]
Гавриленко Сергей Алексеевич
Member

Откуда: Moscow
Сообщений: 37069
Индекс на каждое поле и
SELECT * FROM @tab
WHERE date1 BETWEEN @date_begin AND @date_end
union SELECT * FROM @tab
WHERE date2 BETWEEN @date_begin AND @date_end
union SELECT * FROM @tab
WHERE date3 BETWEEN @date_begin AND @date_end
union SELECT * FROM @tab
WHERE date4 BETWEEN @date_begin AND @date_end
union SELECT * FROM @tab
WHERE date5 BETWEEN @date_begin AND @date_end


Сообщение было отредактировано: 20 июл 12, 13:47
20 июл 12, 13:47    [12893257]     Ответить | Цитировать Сообщить модератору
 Re: оптимизация запроса (много раз between) ms sql 2005  [new]
trew
Member

Откуда: Москва
Сообщений: 2646
Гавриленко Сергей Алексеевич,

У меня @tab это:
таблица A id, date1
таблица B id, date2, date3
таблица C id, date4, date5
все связаны через left join к табл А

индексы на даты в исходных таблицах?
Думал, кинуть результать во временнуют таблицу и как-то развернуть UNPIVOT, быстрее будет?
20 июл 12, 14:01    [12893332]     Ответить | Цитировать Сообщить модератору
 Re: оптимизация запроса (много раз between) ms sql 2005  [new]
Гавриленко Сергей Алексеевич
Member

Откуда: Moscow
Сообщений: 37069
Вы запрос покажите, структкру и план.
20 июл 12, 14:08    [12893362]     Ответить | Цитировать Сообщить модератору
 Re: оптимизация запроса (много раз between) ms sql 2005  [new]
iap
Member

Откуда: Москва
Сообщений: 47001
Гавриленко Сергей Алексеевич,

наверно, всё-таки, UNION ALL, а не UNION?

trew,

SMALLDATETIME теоретически может содержать ненулевое время.
Поэтому точнее
WHERE date1 >= @date_begin AND date1 < DATEADD(DAY,1,@date_end)
??
20 июл 12, 14:12    [12893389]     Ответить | Цитировать Сообщить модератору
 Re: оптимизация запроса (много раз between) ms sql 2005  [new]
Гавриленко Сергей Алексеевич
Member

Откуда: Moscow
Сообщений: 37069
iap
Гавриленко Сергей Алексеевич,

наверно, всё-таки, UNION ALL, а не UNION?
Если в две даты попадут под два разных between, в результирующем наборе будет две записи.
20 июл 12, 14:14    [12893396]     Ответить | Цитировать Сообщить модератору
 Re: оптимизация запроса (много раз between) ms sql 2005  [new]
iap
Member

Откуда: Москва
Сообщений: 47001
Гавриленко Сергей Алексеевич,

ой, я неправ! UNION ALL, а во внешнем запросе - DISTINCT.
Хотя, если в таблице есть повторяющиеся записи,
а в диапазон входят сразу несколько проверяемых полей с датами,
запрос с UNIONом в любом случае выдаст неправильный результат.
20 июл 12, 14:19    [12893423]     Ответить | Цитировать Сообщить модератору
 Re: оптимизация запроса (много раз between) ms sql 2005  [new]
iap
Member

Откуда: Москва
Сообщений: 47001
Гавриленко Сергей Алексеевич
iap
Гавриленко Сергей Алексеевич,

наверно, всё-таки, UNION ALL, а не UNION?
Если в две даты попадут под два разных between, в результирующем наборе будет две записи.
А если в таблице две одинаковые записи, UNION вернёт только одну!
20 июл 12, 14:20    [12893430]     Ответить | Цитировать Сообщить модератору
 Re: оптимизация запроса (много раз between) ms sql 2005  [new]
Гавриленко Сергей Алексеевич
Member

Откуда: Moscow
Сообщений: 37069
iap
Гавриленко Сергей Алексеевич
пропущено...
Если в две даты попадут под два разных between, в результирующем наборе будет две записи.
А если в таблице две одинаковые записи, UNION вернёт только одну!
id int unique
20 июл 12, 14:21    [12893440]     Ответить | Цитировать Сообщить модератору
 Re: оптимизация запроса (много раз between) ms sql 2005  [new]
iap
Member

Откуда: Москва
Сообщений: 47001
Гавриленко Сергей Алексеевич
iap
пропущено...
А если в таблице две одинаковые записи, UNION вернёт только одну!
id int unique
А!
Слона-то я и не заметил
20 июл 12, 14:37    [12893546]     Ответить | Цитировать Сообщить модератору
 Re: оптимизация запроса (много раз between) ms sql 2005  [new]
invm
Member

Откуда: Москва
Сообщений: 9413
select
 *
from
 @tab
where
 exists(
  select
   *
  from
   (values (date1), (date2), (date3), (date4), (date5)) t(d)
  where
   d between @date_begin and @date_end
 );
20 июл 12, 15:20    [12893817]     Ответить | Цитировать Сообщить модератору
 Re: оптимизация запроса (много раз between) ms sql 2005  [new]
trew
Member

Откуда: Москва
Сообщений: 2646
invm,
У меня MS SQL 2005. Поэтому не работает Ваш запрос.

На каждой дате построил некластерный индекс.
  SELECT  
	q.obj_id
	,q.solution_datetime  
	,sb.acceptance_date
    ,sb.rejection_date
	,ak.acceptance_date
    ,ak.rejection_date    
FROM tab1 q 
	LEFT JOIN tab2 sb  
	ON sb.questnr_id = q.obj_id
	LEFT JOIN tab3 ak 
	ON ak.questnr_id = q.obj_id
WHERE 
	q.solution_datetime >= @date_begin AND q.solution_datetime <= @date_end
	OR sb.acceptance_date >= @date_begin AND sb.acceptance_date <= @date_end
	OR sb.rejection_date >= @date_begin AND sb.rejection_date <= @date_end
	OR ak.acceptance_date >= @date_begin AND ak.acceptance_date <= @date_end
	OR ak.rejection_date >= @date_begin AND ak.rejection_date <= @date_end



 |--Parallelism(Gather Streams)
       |--Filter(WHERE:([DB_NEW].[dbo].[tab1].[solution_datetime] as [q].[solution_datetime]>=[@date_begin] AND [DB_NEW].[dbo].[tab1].[solution_datetime] as [q].[solution_datetime]<=[@date_end] OR [DB_NEW].[dbo].[retcr_security_i
            |--Hash Match(Right Outer Join, HASH:([ak].[questnr_id])=([q].[obj_id]))
                 |--Parallelism(Repartition Streams, Hash Partitioning, PARTITION COLUMNS:([ak].[questnr_id]))
                 |    |--Clustered Index Scan(OBJECT:([DB_NEW].[dbo].[tab3].[pk_tab3] AS [ak]))
                 |--Hash Match(Right Outer Join, HASH:([sb].[questnr_id])=([q].[obj_id]))
                      |--Parallelism(Repartition Streams, Hash Partitioning, PARTITION COLUMNS:([sb].[questnr_id]))
                      |    |--Clustered Index Scan(OBJECT:([DB_NEW].[dbo].[tab2].[pk_tab2] AS [sb]))
                      |--Parallelism(Repartition Streams, Hash Partitioning, PARTITION COLUMNS:([q].[obj_id]))
                           |--Index Scan(OBJECT:([DB_NEW].[dbo].[tab1].[inx_solution_date] AS [q]))
20 июл 12, 15:38    [12893957]     Ответить | Цитировать Сообщить модератору
 Re: оптимизация запроса (много раз between) ms sql 2005  [new]
invm
Member

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

12893257
20 июл 12, 15:50    [12894050]     Ответить | Цитировать Сообщить модератору
 Re: оптимизация запроса (много раз between) ms sql 2005  [new]
trew
Member

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

SELECT * FROM @tab

В таблицые @tab 230 тыс.записей. Может её во временную табл. кинуть, чтобы чтение было одно.

А потом уже это?
12893257
20 июл 12, 15:57    [12894098]     Ответить | Цитировать Сообщить модератору
 Re: оптимизация запроса (много раз between) ms sql 2005  [new]
invm
Member

Откуда: Москва
Сообщений: 9413
Зачем таблицу целиком во временную переписывать?
20 июл 12, 16:00    [12894118]     Ответить | Цитировать Сообщить модератору
 Re: оптимизация запроса (много раз between) ms sql 2005  [new]
trew
Member

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

Получается так (исходные таблицы А, B и С)
SELECT id, date1 FROM A
WHERE date1 BETWEEN @date_begin AND @date_end
union 
SELECT id, date2 FROM B
WHERE date2 BETWEEN @date_begin AND @date_end
union 
SELECT  id, date3 FROM B
WHERE date3 BETWEEN @date_begin AND @date_end
union 
SELECT id, date4 FROM C
WHERE date4 BETWEEN @date_begin AND @date_end
union 
SELECT id, date5 FROM C
WHERE date5 BETWEEN @date_begin AND @date_end

К таблицам В и С обращение два раза.

Т.е. если мне нужны только уникальные id, сделать так (фрагмент ниже)
SELECT id FROM B
WHERE date2 BETWEEN @date_begin AND @date_end OR date3 BETWEEN @date_begin AND @date_end
20 июл 12, 16:12    [12894199]     Ответить | Цитировать Сообщить модератору
 Re: оптимизация запроса (много раз between) ms sql 2005  [new]
Гавриленко Сергей Алексеевич
Member

Откуда: Moscow
Сообщений: 37069
Нет. Нужно из одного запроса с пятью or'ам сделать пять таких же запросов, но с одним or'ом, после чего объединить из union.
20 июл 12, 16:14    [12894210]     Ответить | Цитировать Сообщить модератору
 Re: оптимизация запроса (много раз between) ms sql 2005  [new]
trew
Member

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

Хотя так не получится, уменя там LEFT JOIN
20 июл 12, 16:14    [12894215]     Ответить | Цитировать Сообщить модератору
 Re: оптимизация запроса (много раз between) ms sql 2005  [new]
Ivan Durak
Member

Откуда: Minsk!!!
Сообщений: 3618
trew
invm,
У меня MS SQL 2005. Поэтому не работает Ваш запрос.

На каждой дате построил некластерный индекс.
  SELECT  
	q.obj_id
	,q.solution_datetime  
	,sb.acceptance_date
    ,sb.rejection_date
	,ak.acceptance_date
    ,ak.rejection_date    
FROM tab1 q 
	LEFT JOIN tab2 sb  
	ON sb.questnr_id = q.obj_id
	LEFT JOIN tab3 ak 
	ON ak.questnr_id = q.obj_id
WHERE 
	q.solution_datetime >= @date_begin AND q.solution_datetime <= @date_end
	OR sb.acceptance_date >= @date_begin AND sb.acceptance_date <= @date_end
	OR sb.rejection_date >= @date_begin AND sb.rejection_date <= @date_end
	OR ak.acceptance_date >= @date_begin AND ak.acceptance_date <= @date_end
	OR ak.rejection_date >= @date_begin AND ak.rejection_date <= @date_end



 |--Parallelism(Gather Streams)
       |--Filter(WHERE:([DB_NEW].[dbo].[tab1].[solution_datetime] as [q].[solution_datetime]>=[@date_begin] AND [DB_NEW].[dbo].[tab1].[solution_datetime] as [q].[solution_datetime]<=[@date_end] OR [DB_NEW].[dbo].[retcr_security_i
            |--Hash Match(Right Outer Join, HASH:([ak].[questnr_id])=([q].[obj_id]))
                 |--Parallelism(Repartition Streams, Hash Partitioning, PARTITION COLUMNS:([ak].[questnr_id]))
                 |    |--Clustered Index Scan(OBJECT:([DB_NEW].[dbo].[tab3].[pk_tab3] AS [ak]))
                 |--Hash Match(Right Outer Join, HASH:([sb].[questnr_id])=([q].[obj_id]))
                      |--Parallelism(Repartition Streams, Hash Partitioning, PARTITION COLUMNS:([sb].[questnr_id]))
                      |    |--Clustered Index Scan(OBJECT:([DB_NEW].[dbo].[tab2].[pk_tab2] AS [sb]))
                      |--Parallelism(Repartition Streams, Hash Partitioning, PARTITION COLUMNS:([q].[obj_id]))
                           |--Index Scan(OBJECT:([DB_NEW].[dbo].[tab1].[inx_solution_date] AS [q]))

Попробуй

SELECT SELECT  
	 q.obj_id
	,q.solution_datetime  
	,sb.acceptance_date
    ,sb.rejection_date
	,ak.acceptance_date
    ,ak.rejection_date    
FROM 
(
	Select Obj_id 
	from tab1 
	WHERE q.solution_datetime >= @date_begin AND q.solution_datetime <= @date_end

	union 

	SELECT questnr_id as Obj_id
	FROM tab2 sb  
	where acceptance_date >= @date_begin AND acceptance_date <= @date_end

	union 

	SELECT questnr_id as Obj_id
	FROM tab2 sb  
	where rejection_date >= @date_begin AND rejection_date <= @date_end

	union 

	SELECT questnr_id as Obj_id
	FROM tab3 sb  
	where acceptance_date >= @date_begin AND acceptance_date <= @date_end

	union 

	SELECT questnr_id as Obj_id
	FROM tab3 sb  
	where rejection_date >= @date_begin AND rejection_date <= @date_end
) SUB
inner join tab1 q on q.Obj_id = SUB.Obj_id
left join tab2 sb on sb.questnr_id = SUB.Obj_id
left join tab3 ak on ak.questnr_id = SUB.Obj_id
20 июл 12, 16:15    [12894216]     Ответить | Цитировать Сообщить модератору
 Re: оптимизация запроса (много раз between) ms sql 2005  [new]
trew
Member

Откуда: Москва
Сообщений: 2646
Ivan Durak,
Не подходит, дольше работает.

Это не понятно 12894210

12893257 @tab это 250тыс.записей. Т.е. 5 раз обращаться к таблицам?
20 июл 12, 16:37    [12894350]     Ответить | Цитировать Сообщить модератору
 Re: оптимизация запроса (много раз between) ms sql 2005  [new]
NIIIK
Member

Откуда: Россия, Ростовская область, г. Таганрог
Сообщений: 1295
trew,

Если бы вы таблицы с интервалами сделали бы как дочернуюю сущность, а не как 4 пары одинаковых атрибутов на уровне родетельской сущности, то тогда было бы проще найти нужне строчки для вашей "@tab.id".
Вообщем вам нужно а-дя @tabPeriods что-то. Но делать такие манипуляции на лету для каждого запроса - дорого.
20 июл 12, 17:27    [12894553]     Ответить | Цитировать Сообщить модератору
 Re: оптимизация запроса (много раз between) ms sql 2005  [new]
Сергей Васкецов
Member

Откуда:
Сообщений: 20362
trew
5 раз обращаться к таблицам?

А индекс по всем 5 датам уже предлагали?
зы. Стойкое ощущение, что задача - часть большой и неверно нешаемой проблемы.
20 июл 12, 18:42    [12894761]     Ответить | Цитировать Сообщить модератору
 Re: оптимизация запроса (много раз between) ms sql 2005  [new]
Гавриленко Сергей Алексеевич
Member

Откуда: Moscow
Сообщений: 37069
Сергей Васкецов
trew
5 раз обращаться к таблицам?

А индекс по всем 5 датам уже предлагали?
Первым ответом: 12893257
20 июл 12, 19:13    [12894819]     Ответить | Цитировать Сообщить модератору
 Re: оптимизация запроса (много раз between) ms sql 2005  [new]
Сергей Васкецов
Member

Откуда:
Сообщений: 20362
Гавриленко Сергей Алексеевич
Сергей Васкецов
пропущено...
А индекс по всем 5 датам уже предлагали?
Первым ответом: 12893257

Индекс. Один. А не 5 индексов и 5 запросов через union.
20 июл 12, 19:15    [12894827]     Ответить | Цитировать Сообщить модератору
 Re: оптимизация запроса (много раз between) ms sql 2005  [new]
Гавриленко Сергей Алексеевич
Member

Откуда: Moscow
Сообщений: 37069
Сергей Васкецов
Индекс. Один. А не 5 индексов и 5 запросов через union.
Один индекс на 5 полей в трех таблицах? Хоть и бесполезно, но оригинально.
20 июл 12, 19:16    [12894831]     Ответить | Цитировать Сообщить модератору
Топик располагается на нескольких страницах: [1] 2   вперед  Ctrl      все
Все форумы / Microsoft SQL Server Ответить