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

Откуда: Киев
Сообщений: 77
есть запрос, который в у прощенном виде выглядит так:
declare @Target as table (id1 int, value1 varchar(50),id2 int, value2 varchar(50))
insert into @Target(id1,id2) select 1,2

declare @dictionary as table(id int, name varchar(50))	
insert into @dictionary
values(1,'Ivan'),(2,'Billy')

select t.id1, d1.name as Value1,t.id2, d2.name as Value2
from @Target t
join @dictionary d1 on d1.id = t.id1
join @dictionary d2 on d2.id = t.id2


из-за двух соединений с таблицей @Dictionary поиск по ней происходит дважды. В реальном случае этих джойнов 6 штук. И поиск по таблице происходит 6 раз.

Можно ли получить тот же результат за одно сканирование таблицы @Dictionary ?
19 окт 15, 14:27    [18297225]     Ответить | Цитировать Сообщить модератору
 Re: Помогите оптимизировать запрос  [new]
Павел Воронцов
Member

Откуда: Новосибирск
Сообщений: 2385
Блог
ilyaBS
Можно ли получить тот же результат за одно сканирование таблицы @Dictionary ?
А зачем? Эти подзапросы сильно тормозят? Там нет индекса по ид? Он не работает? Почему
19 окт 15, 14:33    [18297273]     Ответить | Цитировать Сообщить модератору
 Re: Помогите оптимизировать запрос  [new]
Pavel1211
Member

Откуда: Екатеринбург
Сообщений: 205
ilyaBS, Была как то смежная проблема. Решили вот так:
create table #t1 ( NumberID int identity( 1, 1 ), Number nvarchar(20) )
insert into #t1 ( Number )  values ( '111' ), ( '222' ), ( '333' )

create table #t2 ( FirstNumber nvarchar(20), SecondNumber nvarchar(20) )
insert into #t2 values ( '111', '222' ), ( '333', '444' )


select FirstNumber, SecondNumber
  , max ( case when FirstNumber  = Number then NumberID   else null end ) as [FirstNumberID] 
  , max ( case when SecondNumber = Number then NumberID   else null end ) as [SecondNumberID]
  from #t2 t
  join #t1 n1
    on t.FirstNumber  = n1.Number
    or t.SecondNumber = n1.Number
  group by FirstNumber, SecondNumber  


Не совсем ваш случай, но вдруг поможет
19 окт 15, 14:39    [18297331]     Ответить | Цитировать Сообщить модератору
 Re: Помогите оптимизировать запрос  [new]
alexeyvg
Member

Откуда: Moscow
Сообщений: 31437
ilyaBS
Можно ли получить тот же результат за одно сканирование таблицы @Dictionary ?
Нет. Вам же для одной записи @Target нужно получить две записи в @dictionary, значит, будет два поиска.

Не, можно извратиться, сделать запрос с одной таблицей @dictionary, а потом получить нужный результат через PIVOT, только это будет явно медленнее.
19 окт 15, 14:40    [18297346]     Ответить | Цитировать Сообщить модератору
 Re: Помогите оптимизировать запрос  [new]
o-o
Guest
ilyaBS
из-за двух соединений с таблицей @Dictionary поиск по ней происходит дважды. В реальном случае этих джойнов 6 штук. И поиск по таблице происходит 6 раз.
Можно ли получить тот же результат за одно сканирование таблицы @Dictionary ?

чтобы не было 6 джойнов
в отдельной базе для отчетов
ночью вот такой запрос *материализуют*,
т.е. денормализируют исходную таблицу.
утром отчетники уже работают с одной таблицей вместо 7.
т.к. они еще к этому до кучи джойнов добавят все равно.
и кстати, когда они 20 соединений добавляют, приходится их заставлять через временные таблицы делать.
проджойнил половину -- сложи в #tmp,
потом остальное лепи.
и реально быстрее становится
19 окт 15, 14:59    [18297470]     Ответить | Цитировать Сообщить модератору
 Re: Помогите оптимизировать запрос  [new]
ilyaBS
Member

Откуда: Киев
Сообщений: 77
спасибо павел, алексей. вот так и колдую. еще была у меня версия одна, но пока не доделал.

тbпо такого:
update @target 
set value1 = case when id1 = d.id then d.name else value1 end
  , value2 = cae when id2 = d.id then d.name else value2 end
from @Dictionary


но такое работает в частных случаях при удачной сортировке. еще поищу...
19 окт 15, 15:07    [18297513]     Ответить | Цитировать Сообщить модератору
 Re: Помогите оптимизировать запрос  [new]
WarAnt
Member

Откуда: Питер
Сообщений: 2421
ilyaBS,

Вот такой изврат могу предложить:)
declare @Target as table (id1 int, value1 varchar(50),id2 int, value2 varchar(50),id3 int, value3 varchar(50),id4 int, value4 varchar(50))
insert into @Target(id1,id2, id3, id4) select 1,2, 3, 4

declare @dictionary as table(id int, name varchar(50))	
insert into @dictionary
values(1,'Ivan'),(2,'Billy'),(3,'Tilly'),(4,'Shvilly')

select 
max(case when id1 = id then name else null end),
max(case when id2 = id then name else null end),
max(case when id3 = id then name else null end),
max(case when id4 = id then name else null end)
from @Target t
join @dictionary d1 on d1.id in (id1, id2, id3, id4)
19 окт 15, 15:08    [18297517]     Ответить | Цитировать Сообщить модератору
 Re: Помогите оптимизировать запрос  [new]
iap
Member

Откуда: Москва
Сообщений: 47000
ilyaBS
еще поищу...
чего там искать. Надо писать столько джойнов, сколько нужно.
19 окт 15, 15:10    [18297535]     Ответить | Цитировать Сообщить модератору
 Re: Помогите оптимизировать запрос  [new]
MasterZiv
Member

Откуда: Питер
Сообщений: 34621
ilyaBS
из-за двух соединений с таблицей @Dictionary поиск по ней происходит дважды. В реальном случае этих джойнов 6 штук. И поиск по таблице происходит 6 раз.


Нет смысла оптимизировать выдуманные запросы, аналогичные (в твоём представлении) каким-то твоим другим запросам.


ilyaBS
Можно ли получить тот же результат за одно сканирование таблицы @Dictionary ?


Нет. Кроме того, JOIN -- очень лёгкая операция, и её не нужно пытаться экономить.

Всё, что тебе нужно для хорошей работы данного запроса -- иметь индекс на условие JOIN-а в дочерней таблице,
в данном случае на @dictionary(id).

Естественно, это всё не для тестого случая, для трёх записей индексы не нужны вообще.
19 окт 15, 15:11    [18297543]     Ответить | Цитировать Сообщить модератору
 Re: Помогите оптимизировать запрос  [new]
alexeyvg
Member

Откуда: Moscow
Сообщений: 31437
ilyaBS
из-за двух соединений с таблицей @Dictionary поиск по ней происходит дважды. В реальном случае этих джойнов 6 штук. И поиск по таблице происходит 6 раз.
Ну, у вас вообще поиска не происходит, происходит сканирование. Может, просто индекс добавить в @Dictionary, и проблема решится?

Ещё, если @dictionary очень маленькая, а @Target очень большая, то можно сделать таблицу @dictionary1, с всеми вариантами сочетаний всех 6-ти ID, и джойнить с ней :-)
19 окт 15, 15:12    [18297558]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить