Добро пожаловать в форум, Guest >> Войти | Регистрация | Поиск | Правила | | В избранное | Подписаться | ||
Все форумы / Microsoft SQL Server |
![]() ![]() |
dab2 Member Откуда: Воронеж Сообщений: 846 |
Из тестового задания. Приведенный ниже запрос работает несколько минут. SELECT SUM(Skidka) FROM TovarySkid AS T WITH(NOLOCK) INNER JOIN Skid AS S WITH(NOLOCK) ON (T.Skd=S.Skd) AND (S.Data BETWEEN '01/01/19' AND '01/31/19') Поля TovarySkid.Skd и Skid.Skd индексированы кластерным индексом, Skid.Data проиндексированы некластеризованным индексом. Задача минимум: Написать этот запрос так, чтобы он работал на этих данных за указанный период менее минуты. Предложите, как нужно проиндексировать эти данные дополнительно, чтобы выполнить поставленную задачу? Задача максимум: Написать этот запрос так, чтобы он работал на этих данных менее минуты за любой период. Насколько я понимаю, конструкцию ON ... AND надо заменить на On ... Where. ============================================================================================================ "О, сколько нам открытий чудных готовит просвещения дух, и опыт - сын ошибок трудных, и гений - парадоксов друг, и случай - бог изобретатель" (Пушкин, однако). |
18 дек 19, 14:06 [22043156] Ответить | Цитировать Сообщить модератору |
iiyama Member Откуда: Сообщений: 642 |
dab2, и где план запроса? |
18 дек 19, 14:10 [22043163] Ответить | Цитировать Сообщить модератору |
Akina Member Откуда: Зеленоград, Москва, Россия Сообщений: 21056 |
Skidka - из какой таблицы?CREATE INDEX idx ON Skid (Skd, Data)- должно помочь...
|
||||
18 дек 19, 14:11 [22043164] Ответить | Цитировать Сообщить модератору |
dab2 Member Откуда: Воронеж Сообщений: 846 |
iiyama, план пришлю немного погодя, если удастся получить (база не у меня). |
18 дек 19, 14:17 [22043171] Ответить | Цитировать Сообщить модератору |
dab2 Member Откуда: Воронеж Сообщений: 846 |
Akina, индекс Skid (Skd, Data) не помог, выполнение больше 3 минут. |
18 дек 19, 14:59 [22043240] Ответить | Цитировать Сообщить модератору |
invm Member Откуда: Москва Сообщений: 9693 |
Нужно (Data, Skd) include (Skidka) или (Data) include (Skd, Skidka), если Skidka в таблице Skid. А вообще, пока не покажете хотя бы структуру таблиц, предлагать варианты бессмысленно. Сообщение было отредактировано: 18 дек 19, 15:24 |
||||
18 дек 19, 15:22 [22043278] Ответить | Цитировать Сообщить модератору |
dab2 Member Откуда: Воронеж Сообщений: 846 |
Таблицы сконструированы так: Skid
TovarySkid
По сути, SUM(TovarySkid.Skidka) - проиндексированное поле, а Skid.Data тоже индексировано. Поля связи: Skid.Skd - ключевое поле, TovarySkid.Skd - индекс. |
||
20 дек 19, 03:59 [22044843] Ответить | Цитировать Сообщить модератору |
dab2 Member Откуда: Воронеж Сообщений: 846 |
Ещё была мысль создать внешний ключ ALTER TABLE dbo.Skid ADD CONSTRAINT FK_Skid FOREIGN KEY (Skd) REFERENCES dbo.TovarySkid (Skd) ON UPDATE CASCADE; Но прав пока нет. Или как-то запрос переделать всё же надо? |
20 дек 19, 04:47 [22044852] Ответить | Цитировать Сообщить модератору |
aleks222 Member Откуда: Сообщений: 1299 |
-- 1. Индекс на dbo.TovarySkid CREATE NONCLUSTERED INDEX X_skd ON dbo.TovarySkid(Skd) INCLUDE (Skidka); go -- индекс на dbo.Skid CREATE NONCLUSTERED INDEX X_data ON dbo.Skid(Data) INCLUDE(Skd); go -- решит проблему "чтобы он работал на этих данных за указанный период менее минуты" with t as ( select Skd, Skidka = sum(Skidka) from dbo.TovarySkid where Skidka is not null group by Skd ) , s as ( select * from dbo.Skid where Data BETWEEN '20190101' AND '20190131' ) SELECT SUM(t.Skidka) FROM s INNER JOIN t ON (t.Skd=s.Skd) -- 2. Индексированное View alter view dbo.TovarySkid_Skd_Skidka with schemabinding as select Skd, Skidka = sum(Skidka), count_big(*) as cnt from dbo.TovarySkid where Skidka is not null group by Skd; go create unique clustered index CIX_TovarySkid_Skd_Skidka on dbo.TovarySkid_Skd_Skidka(Skd); go --решит проблему "чтобы он работал на этих данных менее минуты за любой период" with t as ( select * from dbo.TovarySkid_Skd_Skidka with(noexpand)) , s as ( select * from dbo.Skid where Data BETWEEN '20190101' AND '20190131' ) SELECT SUM(t.Skidka) FROM s INNER JOIN t ON (t.Skd=s.Skd) Сообщение было отредактировано: 20 дек 19, 06:25 |
||||
20 дек 19, 06:17 [22044859] Ответить | Цитировать Сообщить модератору |
dab2 Member Откуда: Воронеж Сообщений: 846 |
Вот этот сработал за 2 с! With s as (SELECT * FROM dbo.Skid WHERE Skid.Data BETWEEN '20190901' AND '20190931') SELECT SUM(Skidka) as Скидка FROM TovarySkid WHERE EXISTS (SELECT Skd FROM S WHERE TovarySkid.Skd=S.Skd) |
21 дек 19, 02:06 [22045757] Ответить | Цитировать Сообщить модератору |
dab2 Member Откуда: Воронеж Сообщений: 846 |
With s as (SELECT * FROM dbo.Skid WHERE Skid.Data BETWEEN '20190901' AND '20190931') SELECT SUM(Skidka) as Скидка FROM TovarySkid WHERE EXISTS (SELECT Skd FROM S WHERE TovarySkid.Skd=S.Skd) |
21 дек 19, 02:06 [22045758] Ответить | Цитировать Сообщить модератору |
Все форумы / Microsoft SQL Server | ![]() |