Anteckning
Åtkomst till den här sidan kräver auktorisering. Du kan prova att logga in eller ändra kataloger.
Åtkomst till den här sidan kräver auktorisering. Du kan prova att ändra kataloger.
Den här artikeln hjälper dig att kringgå problemet där du får sämre prestanda för SQL Server när du kör TOP
, MAX
eller MIN
aggregeringssatsen på kolumner.
Ursprunglig produktversion: SQL Server
Ursprungligt KB-nummer: 2965553
Symptom
Anta att du har partitionerade tabeller i Microsoft SQL Server. När du kör en TOP
, MAX
eller MIN
aggregeringssats på kolumner i tabellerna kan du få sämre prestanda.
Kommentar
Det här problemet uppstår bara inte i partitioneringskolumnen.
Lösning
Du kan undvika det här problemet genom att skapa en fråga som samlar in de översta N-elementen i varje partition. Leta sedan reda på TOP N-elementen från den samlingen med element.
Du har till exempel en T1-tabell som har fyra partitioner och partitionsfunktionen är PF1
. Tabellen är partitionerad i kolumnen PCOL
och har index på idx_c1
T1.c1
. Du kan stöta på prestandaproblemet när du kör följande fråga:
SELECT TOP 3 T1.c1, T1.c2
FROM dbo.T1
ORDER BY T1.c1
Undvik problemet så här:
Hitta de tre översta elementen i en viss partition <partition_number>:
SELECT TOP 3 T1.c1, T1.c2 FROM dbo.T1 WHERE $PARTITION.PF1(PCOL) = < **partition_number** > AS A(c1, c2) ORDER BY T1.c1;
Hitta de tre översta elementen i alla fyra partitionerna:
SELECT TOP 3 A.c1, A.c2 FROM (VALUES((1),(2),(3),(4)) AS P( partition_number ) CROSS APPLY ( SELECT TOP 3 (T1.c1, T2.c2) FROM dbo.T1 WHERE $PARTITION.PF1(T1.PCOL) = P.partition_number ORDER BY T1.c1 ) AS A ORDER BY A.c1
Om tabellen är ompartitionerad måste du tyvärr skriva om de här frågorna för att kunna använda det nya antalet partitioner. Du kan dock också hämta antalet partitioner från
sys.partitions
. I stället för att använda en konstant lista över partitioner kan du därför använda följande SQL-skript:SELECT TOP 3 A.c1, A.c2 FROM sys.partitions AS P CROSS APPLY ( SELECT TOP 3 T1.c1, T2.c2) FROM dbo.T1 WHERE $PARTITION.PF1(T1.col1) = P.partition_number ORDER BY T1.c1 ) AS A WHERE P.object_id = OBJECT_ID('dbo.T1') AND P.index_id = INDEXPROPERTY( OBJECTID('dbo.T1'), 'idx_c1', 'INDEXID') ORDER BY a;
Kommentar
Den här artikeln använder TOP N med en order by-sats som exempel.
MAX
ochMIN
satser har liknande problem. Därför kan de bearbetas genom att omvandla dem till TOP 1-frågor, med ordningen inställd på antingen stigande eller fallande.
Mer information
När du frågar efter de ÖVERSTA N raderna i en indexerad kolumn i en icke-partitionerad tabell har frågan vanligtvis bra prestanda. Det beror på att frågeplanen söker igenom ett index för att avgöra vilka de översta n elementen är.
Men för en partitionerad tabell är detta för närvarande inte fallet, eftersom indexen också kan partitioneras. Det innebär att du inte bara kan fråga indexen för att fastställa de översta N elementen. Dessa element kan distribueras över alla partitioner. Tänk dig till exempel följande fall där du har en tabell "a" med två partitioner P0 och P1 som är partitionerade runt 0:
Partition | Tangent | Värde |
---|---|---|
P0 | -2 | 1 |
P0 | -1 | 1 |
P0 | 0 | 12 |
P1 | 1 | 1 |
P1 | 2 | 1 |
P1 | 3 | 15 |
Eftersom varje index är partitionerat kan SQL Server inte skanna indexet samtidigt för att fastställa det maximala värdet. I stället genomsöker den varje element i tabellen för att fastställa maxvärdet. I en tabell som har miljontals rader kan den här processen vara ineffektiv.