Я пытаюсь установить некоторые данные для вычисления нескольких медианов в SQL Server 2008, но у меня проблема с производительностью. Прямо сейчас, я использую это pattern ([еще один пример bottom). Да, я не использую CTE, но использование одного из них не будет устранять проблему, которая у меня есть, и производительность невысока, потому что подзапросы row_number выполняются серийно, а не параллельно.Несколько запросов Row_Number() в одном запросе SQL
Вот полный пример. Ниже SQL я объясняю проблему больше.
-- build the example table
CREATE TABLE #TestMedian (
StateID INT,
TimeDimID INT,
ConstructionStatusID INT,
PopulationSize BIGINT,
SquareMiles BIGINT
);
INSERT INTO #TestMedian (StateID, TimeDimID, ConstructionStatusID, PopulationSize, SquareMiles)
VALUES (1, 1, 1, 100000, 200000);
INSERT INTO #TestMedian (StateID, TimeDimID, ConstructionStatusID, PopulationSize, SquareMiles)
VALUES (1, 1, 1, 200000, 300000);
INSERT INTO #TestMedian (StateID, TimeDimID, ConstructionStatusID, PopulationSize, SquareMiles)
VALUES (1, 1, 1, 300000, 400000);
INSERT INTO #TestMedian (StateID, TimeDimID, ConstructionStatusID, PopulationSize, SquareMiles)
VALUES (1, 1, 1, 100000, 200000);
INSERT INTO #TestMedian (StateID, TimeDimID, ConstructionStatusID, PopulationSize, SquareMiles)
VALUES (1, 1, 1, 250000, 300000);
INSERT INTO #TestMedian (StateID, TimeDimID, ConstructionStatusID, PopulationSize, SquareMiles)
VALUES (1, 1, 1, 350000, 400000);
--TruNCATE TABLE TestMedian
SELECT
StateID
,TimeDimID
,ConstructionStatusID
,NumberOfRows = COUNT(*) OVER (PARTITION BY StateID, TimeDimID, ConstructionStatusID)
,PopulationSizeRowNum = ROW_NUMBER() OVER (PARTITION BY StateID, TimeDimID, ConstructionStatusID ORDER BY PopulationSize)
,SquareMilesRowNum = ROW_NUMBER() OVER (PARTITION BY StateID, TimeDimID, ConstructionStatusID ORDER BY SquareMiles)
,PopulationSize
,SquareMiles
INTO #MedianData
FROM #TestMedian
SELECT MinRowNum = MIN(PopulationSizeRowNum), MaxRowNum = MAX(PopulationSizeRowNum), StateID, TimeDimID, ConstructionStatusID, MedianPopulationSize= AVG(PopulationSize)
FROM #MedianData T
WHERE PopulationSizeRowNum IN((NumberOfRows + 1)/2, (NumberOfRows + 2)/2)
GROUP BY StateID, TimeDimID, ConstructionStatusID
SELECT MinRowNum = MIN(SquareMilesRowNum), MaxRowNum = MAX(SquareMilesRowNum), StateID, TimeDimID, ConstructionStatusID, MedianSquareMiles= AVG(SquareMiles)
FROM #MedianData T
WHERE SquareMilesRowNum IN((NumberOfRows + 1)/2, (NumberOfRows + 2)/2)
GROUP BY StateID, TimeDimID, ConstructionStatusID
DROP TABLE #MedianData
DROP TABLE #TestMedian
Проблема с этим запросом является то, что SQL Server выполняет оба «ROW__NUMBER() OVER ...» подзапросы в последовательный, а не параллельно. Поэтому, если у меня будет 10 из этих вычислений ROW__NUMBER, они будут вычислять их один за другим, и я получаю линейный рост, который воняет. У меня есть 8-полосная 32-гигабайтная система. Я запускаю этот запрос, и мне бы хотелось, чтобы какой-то параллелизм. Я пытаюсь запустить этот тип запроса в таблице из 5 000 000 строк.
Я могу сказать, что это можно сделать, посмотрев план запроса и увидев Сорта в одном и том же пути выполнения (отображение XML-плана запроса не будет работать хорошо на SO).
Итак, мой вопрос заключается в следующем: как я могу изменить этот запрос так, чтобы запросы ROW_NUMBER выполнялись параллельно? Существует ли совершенно другой метод, который я могу использовать для подготовки данных для нескольких медианных вычислений?
+1, достаточно код, чтобы попробовать его на моей системе !! –
+1, потому что я не знал, что вы можете использовать предложения OVER вне функций ранжирования - и в SQL 2005 тоже не меньше. Woot! –
Philip: для обычных функций агрегации только предложение PARTITION BY, но не часть ORDER BY :-( – RBarryYoung