Próbuję skonfigurować niektóre dane, aby obliczyć wiele median w SQL Server 2008, ale mam problem z wydajnością. W tej chwili używam tego pattern ([inny przykład bottom). Tak, nie używam WRT, ale użycie jednego nie rozwiąże problemu, który mam i tak działa, a wydajność jest niska, ponieważ podokresy wiersza numerycznego są uruchamiane szeregowo, a nie równolegle.Wiele połączeń Row_Number() w pojedynczym zapytaniu SQL
Oto pełny przykład. Poniżej SQL wyjaśniam problem bardziej.
-- 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
Problem z tym jest to, że zapytania SQL Server wykonuje zarówno z "ROW__NUMBER() OVER ..." sub-queries w seryjnym, a nie równolegle. Więc jeśli mam 10 z tych obliczeń ROW__NUMBER, obliczę je jeden po drugim i dostaję liniowy wzrost, który śmierdzi. Mam system 8-kanałowy 32 GB, na którym uruchamiam to zapytanie i chciałbym trochę równoległości. Próbuję uruchomić tego typu kwerendy na 5.000.000 tabeli wiersza.
Mogę powiedzieć, że robi to, patrząc na plan zapytania i widząc Sorts w tej samej ścieżce wykonania (wyświetlanie XML planu kwerendy nie działałoby naprawdę dobrze na SO).
Moje pytanie brzmi następująco: Jak mogę zmienić to zapytanie, aby zapytania ROW_NUMBER były wykonywane równolegle? Czy istnieje zupełnie inna technika, której mogę użyć do przygotowania danych do wielu obliczeń median?
+1, wystarczy kod, aby spróbować go na moim systemie !! –
+1, ponieważ nie wiedziałem, że można używać klauzul OVER poza funkcjami rankingu - również w SQL 2005, nie mniej. Woot! –
Philip: Dla normalnych funkcji Aggregate, tylko klauzula PARTITION BY, a nie część ORDER BY :-( – RBarryYoung