У меня есть запрос, как показано ниже. Могу ли я использовать разбиение по оконной функции вместо группировки и объединения? я должен изменить имя партнера и номер партнера. Также на основе номера партнера меняется одна группа по полю. мой temptable содержит около 24 миллионов записей. я работаю над улучшением производительности этого запроса. в настоящее время выполнение моей хранимой процедуры занимает около 1 часа.
INSERT INTO #FinalResultTable
(
[F1],
[F2],
[F3],
[F4],
[Partner #],
[Partner Name],
[F5],
[F6],
[F7],
[F8],
[Partner Amount (rounded)]
,[Entity Name]
,[Investment Number]
)
SELECT
[F1],
[F2],
[F3],
[F4],
-2 as [Partner #],
'Work Paper Total'
AS [PartnerName], -- VARCHAR
[F5],
[F6],
[F7],
[F8],
MAX([WorkPaperTotal])
, [Entity Name]
,[Investment Number]
FROM #FinalResultTable
WHERE [Partner #] > 0
GROUP BY
[F1],
[F2],
[F3],
[F4],
[F5],
[F6],
[F7],
[F8],
[Entity Name],
[Investment Number]
union all
SELECT
[F1],
[F2],
[F3],
[F4],
-3 as [Partner #],
'Partner Total'
AS [PartnerName], -- VARCHAR
[F5],
[F6],
[F9],
[F10],
MAX([WorkPaperTotal]) -SUM([Partner Amount (rounded)])
, [Entity Name]
,[Investment Number]
FROM #FinalResultTable
WHERE [Partner #] > 0
GROUP BY
[F1],
[F2],
[F3],
[F4],
[F5],
[F6],
[F9],
[F10],
[Entity Name],
[Investment Number]
пожалуйста, дайте свое предложение, чтобы улучшить производительность этого запроса.
Вы фактически дублируете данные, чтобы получить разные суммы. т.е. строка #FinalResultTable входит как в агрегаты, так и в группу агрегатов по разным столбцам. Так что нет, вам нужно UNION ALL и вам нужна агрегация. Вы не можете изменить запрос и получить тот же результат.
Рассмотрите возможность использования таблиц в памяти и/или индексов columnstore, если вы собираетесь выполнять много такого рода агрегирования временных данных.
@GordonLinoff у нас есть 3 разных типа партнеров. номера партнеров будут -1,-2 и -3. на основе этого номера партнера расчет суммы партнера будет другим. Также будет другим имя партнера. Раньше он использовал цикл while. но это заняло больше времени, так как у него есть 3 разных вставки. я пытался удалить его с объединением всех. это немного улучшило производительность. еще не много. я работаю над улучшением производительности. но я новичок в работе с базой данных. Есть 24 миллиона записей. это занимает 1,5 часа сейчас.
@ThorstenKettner, как мы можем это сделать? Извините, как упоминалось в комментарии выше, я новичок в работе с базами данных. до того, как он использовал цикл while, который будет вставлять данные три раза. но вставка данных занимала время. поэтому я подумал о том, чтобы избежать этого, используя одиночную вставку.
@JeroenMostert Я понятия не имею о таблице в памяти и индексе столбца, я буду искать ее. если у вас есть пример, не могли бы вы поделиться


Я упрощаю запрос. У вас есть такие данные:
F1 | F7 | F9 | WorkPaperTotal | PartnerAmount ---+----+----+----------------+-------------- 1 | 1 | 1 | 1000 | 10 1 | 1 | 2 | 2000 | 20 1 | 2 | 1 | 3000 | 30 1 | 2 | 2 | 4000 | 40 2 | 1 | 1 | 5000 | 50
И вы хотите результат для
select f1, f7 as f, max(workpapertotal) as result, -2 as partner
from mytable
group by f1, f7
union all
select f1, f9 as f, max(workpapertotal) - sum(partneramount) as result, -3 as partner
from mytable
group by f1, f9;
Первая часть дает вам:
F1 | F | result | partner ---+---+--------+-------- 1 | 1 | 2000 | -2 1 | 2 | 4000 | -2 2 | 1 | 5000 | -2
Вторая часть дает вам:
F1 | F | result | partner ---+---+--------+-------- 1 | 1 | 2960 | -3 1 | 2 | 3940 | -3 2 | 1 | 4950 | -3
Которые делают окончательный результат
F1 | F | result | partner ---+---+--------+-------- 1 | 1 | 2000 | -2 1 | 1 | 2960 | -3 1 | 2 | 4000 | -2 1 | 2 | 3940 | -3 2 | 1 | 5000 | -2 2 | 1 | 4950 | -3
(где F означает F7 для партнера -2 и F9 для партнера -3). Из пяти строк таблицы получается шесть строк результата, несмотря на агрегацию. Таким образом, подход, который вы уже используете для объединения двух запросов, уже является единственным возможным подходом. Я предполагаю, что ваше предложение where (WHERE [Partner #] > 0) не исключает очень много строк, поэтому большая часть данных таблицы должна быть прочитана и отсортирована, а затем сгруппирована для агрегирования. И это должно произойти даже дважды. Это требует времени. Вы мало что можете с этим поделать. Купить оборудование было бы моей первой идеей.
Вы можете попробовать следующие индексы, чтобы предоставить предварительно отсортированные данные. Это предложение СУБД, которое она может принять или не принять для запроса.
CREATE INDEX idx1
ON #FinalResultTable(f1,f2,f3,f4,f5,f6,f7,f8,[Entity Name],[Investment Number])
WHERE [Partner #] > 0;
CREATE INDEX idx2
ON #FinalResultTable(f1,f2,f3,f4,f5,f6,f9,f10,[Entity Name],[Investment Number])
WHERE [Partner #] > 0;
Примеры данных, желаемые результаты и объяснение логики помогут.