Это не ответ «per se», это скорее расширенный комментарий.
План не «сложный», он довольно простой и, кажется, лучший, который вы можете получить (исключая курсор). Две кластеризованные таблицы, seeked и merge join, агрегированные для sum () и помещенные в кластеризованную таблицу в базе данных tempdb для прохождения курсором. Две основные точки (с точки зрения производительности) выглядят следующим образом:
- очевидная вставка кластеризованного индекса (запись строк по 1,3 млн.)
- оператор сортировки перед агрегатом потока. это, скорее всего, разлив в базу данных tempdb для сортировки (1,3 млн строк). Вы можете убедиться в этом, проверив фактический план выполнения.
"Не очень прямое" наблюдение - это число строк: 1,3 мил перед агрегацией и 1,3 мил после агрегации. Предполагается, что агрегация на самом деле не является агрегацией для вычисления сумм (sum () бессмысленна {?}), А скорее похожа на «отдельный тип» агрегации (использование суммы, потому что столбцы inventsum имеют цифры c). Даже отдельная агрегация здесь может не понадобиться, и вы можете проверить это, проверив, действительно ли значения ITEMID (таблицы INVENTSUM) являются уникальными. Если значения не являются уникальными, то проверьте, является ли ITEMID уникальным для AREAID и INVENTDIMID (то есть элемент может появляться только один раз для области & изобретать {ory}). Если любое из них истинно, то для указанного c запроса ITEMID можно считать уникальным, и в результате агрегирование (GROUP BY cols ...) вообще не требуется.
Теоретически, если ITEMID были «уникальными», и целью был микрооптимизация указанного запроса c, тогда «лучшее» выполнение могло быть достигнуто путем кластеризации INVENTSUM по AREAID, INVENTDIMID, ITEMID
[create unique clustered index inventsumclidx on INVENTSUM(AREAID,INVENTDIMID, ITEMID)]
и выбора группы по ITEMID, INVENTDIMID
GROUP BY A.ITEMID, A.INVENTDIMID, B.CONFIGID, B.INVENTSIZEID ....
ORDER BY A.ITEMID, A.INVENTDIMID, B.CONFIGID,..
это исключило бы оператор сортировки перед объединением (вся информация уже отсортирована по INVENTDIMID) и оператор агрегирования (вся информация уникальна). Без разлива в tempdb для сортировки перед SEGMENT возможно сокращение времени выполнения на 50%.
если у вас есть доступный тестовый экземпляр, вы можете попробовать его и проверить, есть ли разница:
--drop existing clustered index
--drop index [I_174ITEMDIMIDX] on dbo.[INVENTSUM]
create unique clustered index inventsumclidx on INVENTSUM(AREAID,INVENTDIMID, ITEMID);
go
--adjust these values
declare @P1 int = 20, @P2 int = 50, @P3 int = 15, @P4 int = 500;
declare cur cursor FAST_FORWARD for
SELECT
SUM(A.POSTEDQTY),SUM(A.POSTEDVALUE),SUM(A.PHYSICALVALUE),SUM(A.DEDUCTED),SUM(A.REGISTERED),SUM(A.RECEIVED),SUM(A.PICKED),SUM(A.RESERVPHYSICAL),SUM(A.RESERVORDERED),SUM(A.ONORDER),SUM(A.ORDERED),SUM(A.ARRIVED),SUM(A.QUOTATIONRECEIPT),SUM(A.QUOTATIONISSUE),SUM(A.PHYSICALINVENT),SUM(A.JSPOTENCIES),SUM(A.JSPOTENCIES2_),SUM(A.JSPOSTEDDUALUNITQTY),SUM(A.JSPICKEDDUALUNITQTY),SUM(A.JSRECEIVEDDUALUNITQTY),SUM(A.JSDEDUCTEDDUALUNITQTY),SUM(A.JSREGISTEREDDUALUNITQTY),SUM(A.AVAILPHYSICAL),SUM(A.AVAILORDERED),A.ITEMID,B.CONFIGID,B.INVENTSIZEID,B.INVENTCOLORID,B.INVENTLOCATIONID,B.WMSLOCATIONID
FROM INVENTSUM A, INVENTDIM B WITH(INDEX(I_698DIMIDIDX))
WHERE ((A.DATAAREAID=@P1) AND ((A.CLOSED=@P2) AND (A.CLOSEDQTY=@P3))) AND ((B.DATAAREAID=@P4) AND (A.INVENTDIMID=B.INVENTDIMID))
GROUP BY A.ITEMID, A.INVENTDIMID, B.CONFIGID,B.INVENTSIZEID,B.INVENTCOLORID,B.INVENTLOCATIONID,B.WMSLOCATIONID
ORDER BY A.ITEMID, A.INVENTDIMID, B.CONFIGID,B.INVENTSIZEID,B.INVENTCOLORID,B.INVENTLOCATIONID,B.WMSLOCATIONID
OPTION(FAST 1);
open cur;
fetch next from cur;
close cur;
deallocate cur;