Dela via


Sämre prestanda för SQL Server när du kör en TOP-, MAX- eller MIN-aggregeringssats på andra kolumner än partitioneringskolumnen

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:

  1. 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;
    
  2. 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
    
  3. 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 och MIN 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.