Comments 16
Сравните планы выполнения, мне кажется, так будет оптимальней:
select t.rn
, t.dealid deal_id
, t.customerid cust_id, c.customername cust_name
, t.nomenclatureid nom_id, nom.nomenclaturename nom_name
, t.dealdate, t.qty
from (
select d.DealID, d.customerid, nomenclatureid
, [COUNT] qty -- нехорошо :(
, dealdate
-- нумеруем отдельно заказы каждого клиента с сортировкой по дате
, ROW_NUMBER() over( partition by customerid order by dealdate desc ) rn
from Deal d
) t
join customer c on( c.customerid = t.customerid )
join nomenclature nom on( nom.nomenclatureid = t.nomenclatureid )
where t.rn <= 10
order by cust_id, dealdate
Или же я не правильно понял задачу.Все правильно.
Большое спасибо, ваш вариент работает быстрее.
Большое спасибо, ваш вариент работает быстрее.
Сравнил план выполнения.
В таблице customer 5000 записей, в таблице Deal около 10 миллионов.
Используя OUTER APPLY:
Время исполнения: 1 сек
Estimated subtree cost: 0,17.
Profiler — CPU: 765
Profiler — Reads: 34973
Profiler — Duration: 783
Используя ROW_NUMBER estimated subtree cost 450.00.
Время исполнения: 48 сек
Estimated subtree cost: 450,00.
Profiler — CPU: 125979
Profiler — Reads: 41707
Profiler — Duration: 47346
В таблице customer 5000 записей, в таблице Deal около 10 миллионов.
Используя OUTER APPLY:
Время исполнения: 1 сек
Estimated subtree cost: 0,17.
Profiler — CPU: 765
Profiler — Reads: 34973
Profiler — Duration: 783
Используя ROW_NUMBER estimated subtree cost 450.00.
Время исполнения: 48 сек
Estimated subtree cost: 450,00.
Profiler — CPU: 125979
Profiler — Reads: 41707
Profiler — Duration: 47346
CREATE INDEX I_Deal ON Deal(CustomerID, DealDate, NomenclatureID)
Индекс построен по возрастанию даты, а везде используется сортировка по убыванию. Предположу, что партишену более западло просматривать 10 миллионов строк в столь непотребном порядке.
Попробовал использовать 4 разных индекса:
Разницы никакой не обнаружил.
По результатам изучения Execution Plan для скриптов, которые приложены к примеру, в любом случае при использовании ROW_NUMBER сначала производится расставление номеров для всех строк, т.е. до фильтра «t.rn <= 10» доходит больше миллиона строк, а уже только после фильтрации получается 30 строк.
CREATE INDEX I_Deal1 ON Deal (CustomerID, DealDate)
CREATE INDEX I_Deal2 ON Deal (CustomerID, DealDate desc)
CREATE INDEX I_Deal3 ON Deal (DealDate desc, CustomerID)
CREATE INDEX I_Deal3 ON Deal (DealDate, CustomerID)
Разницы никакой не обнаружил.
По результатам изучения Execution Plan для скриптов, которые приложены к примеру, в любом случае при использовании ROW_NUMBER сначала производится расставление номеров для всех строк, т.е. до фильтра «t.rn <= 10» доходит больше миллиона строк, а уже только после фильтрации получается 30 строк.
Сгенерировал 1M записей в табличку Deal следующим кодом:
Результат сравним с результатом kuda78
Если судить по ExecutionPlan, cервер сначала нумерует ВСЕ строки таблицы DEALS и только потом начинает перемножать её с другими таблицами.
USE Claims
GO
SET NOCOUNT ON
GO
DECLARE @i INT
SET @i = 1
WHILE @i < 1000000
BEGIN
INSERT INTO Deal(CustomerID, NomenclatureID, [Count], DealDate)
SELECT (@i % 3) + 1, (@i % 3) + 1, 250, DateADD(n, -@i, '2010-01-01')
SET @i = @i + 1
END
Результат сравним с результатом kuda78
Если судить по ExecutionPlan, cервер сначала нумерует ВСЕ строки таблицы DEALS и только потом начинает перемножать её с другими таблицами.
UFO just landed and posted this here
согласен с предыдущим товарищем.
к аффтару: а вы чего такой поверхностный? хоть бы написали, чем cross apply от outer apply отличается.
еще могу порекомендовать прочитать книжку:
www.amazon.com/Microsoft%C2%AE-Server%C2%AE-T-SQL-Fundamentals-PRO-Developer/dp/0735626014
в интернете полно где лежит.
к аффтару: а вы чего такой поверхностный? хоть бы написали, чем cross apply от outer apply отличается.
еще могу порекомендовать прочитать книжку:
www.amazon.com/Microsoft%C2%AE-Server%C2%AE-T-SQL-Fundamentals-PRO-Developer/dp/0735626014
в интернете полно где лежит.
Может быть, но я не ставил целью дать описание оператора, это можно прочитать в MSDN, ссылку я дал.
Просто хотел поделиться с сообществом интересной находкой. Лично я про этот оператор не знал, и он помог мне элегантно решить проблему, которую мы раньше решали неудобно и громоздко.
Если комунибудь из коллег, этот оператор (семейство операторов) поможет решать их задачи, значит я писал этот пост не зря.
Вот, например, решение от abyrvalg я так же считаю интресным, и возму его себе на заметку.
За книжку большое спасибо, на досуге почитаю.
Просто хотел поделиться с сообществом интересной находкой. Лично я про этот оператор не знал, и он помог мне элегантно решить проблему, которую мы раньше решали неудобно и громоздко.
Если комунибудь из коллег, этот оператор (семейство операторов) поможет решать их задачи, значит я писал этот пост не зря.
Вот, например, решение от abyrvalg я так же считаю интресным, и возму его себе на заметку.
За книжку большое спасибо, на досуге почитаю.
Вы попали пальцем в небо, преподносите давно существующую и относительно известную фичу как открытие Америки. Например, кто работает с xml столбцами знает, что без cross apply xml.nodes никуда…
Из примеров кода, которые видел в последнее время, больше всего восхитила остроумная выборка значений поля в таблице в строку с разделителями в один запрос
Из примеров кода, которые видел в последнее время, больше всего восхитила остроумная выборка значений поля в таблице в строку с разделителями в один запрос
select (
select [column] + [delimeter] as 'data()'
from [table] as A
for xml path(''))
Никакой Америки. Просто поиск оптимального решения конкретной задачи.
P.S Коллеги, давайте вопрос известности/неизвестности оператора APPLY оставим вне рамок этой темы, тем более, как показывает статистика, далеко не все, кто применяет TSql, знакомы со всеми его возможностями.
P.S Коллеги, давайте вопрос известности/неизвестности оператора APPLY оставим вне рамок этой темы, тем более, как показывает статистика, далеко не все, кто применяет TSql, знакомы со всеми его возможностями.
> Правый вход оценивается
Имелось в виду вычисляется
Имелось в виду вычисляется
Перевод я тоже взял с MSDN:
http://technet.microsoft.com/ru-ru/library/ms175156.aspx
http://technet.microsoft.com/ru-ru/library/ms175156.aspx
Sign up to leave a comment.
MSSql: Использование оператора APPLY в TSql