sql >> Database teknologi >  >> RDS >> Sqlserver

Selvstudium til SQL Server-tabelopdeling og -partitioner

Problem

I denne artikel vil vi fokusere på demonstrationen af ​​tabelopdeling. Den enkleste forklaring på tabelopdeling kan kaldes at opdele store tabeller i små. Dette emne giver skalerbarhed og håndterbarhed.

Hvad er tabelpartitionering i SQL Server?

Antag, at vi har et bord, og det vokser dag for dag. I dette tilfælde kan tabellen forårsage nogle problemer, som skal løses ved de trin, der er defineret nedenfor:

  • Vedligehold denne tabel. Det vil tage lang tid og forbruge flere ressourcer (CPU, IO osv.).
  • Sikkerhedskopier.
  • Låseproblemer.

Af ovennævnte årsager har vi brug for en bordopdeling. Denne tilgang har følgende fordele:

  • Administrationsevne:Hvis vi skiller tabellen ad, kan vi administrere hver partition i tabellen. For eksempel kan vi kun lave én partition af tabellen.
  • Arkiveringsfunktion:Nogle partitioner i tabellen bruges kun af denne grund. Vi behøver ikke at sikkerhedskopiere denne partition af tabellen. Vi kan kun bruge en filgruppesikkerhedskopi og sikkerhedskopiere den ved at ændre en partition i tabellen.
  • Forespørgselsydeevne:SQL Server-forespørgselsoptimering beslutter at bruge partitioneliminering. Det betyder, at SQL Server ikke foretager nogen søgning efter den ikke-relaterede partition i tabellen.

Lodret og horisontal tabelopdeling i SQL Server

Tabelopdeling er et generelt koncept. Der er adskillige partitioneringstyper, der fungerer i særlige tilfælde. Den mest essentielle og mest brugte er de to tilgange:lodret opdeling og vandret opdeling.

Specificiteten af ​​hver type afspejler essensen af ​​en tabel som en struktur bestående af kolonner og rækker:

• Vertikal partitionering opdeler tabellen i kolonner.
• Vandret partitionering opdeler tabellen i rækker.

Det mest typiske eksempel på lodret tabelopdeling er en tabel med medarbejdere med deres detaljer - navne, e-mails, telefonnumre, adresser, fødselsdage, erhverv, lønninger og alle andre oplysninger, der måtte være nødvendige. En del af sådanne data er fortrolige. Desuden har operatører i de fleste tilfælde kun brug for nogle grundlæggende data som navne og e-mail-adresser.

Den lodrette partitionering skaber flere "snævrere" tabeller med de nødvendige data ved hånden. Forespørgsler er kun målrettet mod en bestemt del. På denne måde reducerer virksomheder belastningen, accelererer opgaverne og sikrer, at fortrolige data ikke afsløres.

Den vandrette tabelopdeling resulterer i, at en generel tabel opdeles i flere mindre, hvor hver partikeltabel har det samme antal kolonner, men antallet af rækker er færre. Det er en standardtilgang til for mange tabeller med kronologiske data.

For eksempel kan en tabel med data for hele året opdeles i mindre sektioner for hver måned eller uge. Derefter vil forespørgslen kun vedrøre én bestemt mindre tabel. Horisontal partitionering forbedrer skalerbarheden for datamængderne med deres vækst. De opdelte tabeller forbliver mindre og nemme at behandle.

Enhver tabelopdeling i SQL-server bør overvejes med omhu. Nogle gange skal du anmode om data fra flere partitionerede tabeller på én gang, og så skal du bruge JOINs i forespørgsler. Desuden kan lodret partitionering stadig resultere i store tabeller, og du bliver nødt til at opdele dem mere. I dit arbejde bør du stole på beslutningerne til dine specifikke forretningsformål.

Nu hvor vi har afklaret konceptet med tabelopdelingen i SQL Server, er det tid til at fortsætte til demonstrationen.

Vi vil undgå ethvert T-SQL-script og håndtere alle tabelpartitionstrinene med SQL Server-partitioneringsguiden.

Hvad skal du bruge for at lave SQL-databasepartitioner?

  • WideWorldImporters Sample Database
  • SQL Server 2017 Developer Edition

Billedet nedenfor viser os, hvordan man designer en bordpartition. Vi vil lave en tabelpartition efter år og finde forskellige filgrupper.

På dette trin vil vi oprette to filgrupper (FG_2013, FG_2014). Højreklik på en database, og klik derefter på fanen Filgrupper.

Nu vil vi forbinde filgrupperne til nye pdf-filer.

Vores databaselagerstruktur er klar til tabelopdeling. Vi finder den tabel, som vi ønsker skal partitioneres, og starter guiden Opret partition.

På skærmbilledet nedenfor vælger vi en kolonne, som vi vil anvende partitionsfunktionen på. Den valgte kolonne er "InvoiceDate".

På de næste to skærme vil vi navngive en partitionsfunktion og et partitionsskema.

En partitionsfunktion vil definere, hvordan man partitionerer for rækkerne [Salg].[Invoices] baseret på kolonnen InvoiceDate.

Et partitionsskema vil definere kort for Sales.Invoices-rækkerne til filgrupper.

Tildel partitionerne til filgrupper og indstil grænserne.

Venstre/Højre grænse definerer siden af ​​hvert grænseværdiinterval, som kan være venstre eller højre. Vi sætter grænser som denne og klikker på Estimer lagerplads. Denne mulighed giver os oplysninger om antallet af rækker, der skal placeres i grænserne.

Og til sidst vil vi vælge Kør med det samme og derefter klikke på Næste.

Når handlingen er vellykket, skal du klikke på Luk.

Som du kan se, er vores Sales.Invoices-tabel blevet opdelt. Denne forespørgsel vil vise detaljerne i den opdelte tabel.

SELECT
  OBJECT_SCHEMA_NAME(pstats.object_id) AS SchemaName
  ,OBJECT_NAME(pstats.object_id) AS TableName
  ,ps.name AS PartitionSchemeName
  ,ds.name AS PartitionFilegroupName
  ,pf.name AS PartitionFunctionName
  ,CASE pf.boundary_value_on_right WHEN 0 THEN 'Range Left' ELSE 'Range Right' END AS PartitionFunctionRange
  ,CASE pf.boundary_value_on_right WHEN 0 THEN 'Upper Boundary' ELSE 'Lower Boundary' END AS PartitionBoundary
  ,prv.value AS PartitionBoundaryValue
  ,c.name AS PartitionKey
  ,CASE 
    WHEN pf.boundary_value_on_right = 0 
    THEN c.name + ' > ' + CAST(ISNULL(LAG(prv.value) OVER(PARTITION BY pstats.object_id ORDER BY pstats.object_id, pstats.partition_number), 'Infinity') AS VARCHAR(100)) + ' and ' + c.name + ' <= ' + CAST(ISNULL(prv.value, 'Infinity') AS VARCHAR(100)) 
    ELSE c.name + ' >= ' + CAST(ISNULL(prv.value, 'Infinity') AS VARCHAR(100))  + ' and ' + c.name + ' < ' + CAST(ISNULL(LEAD(prv.value) OVER(PARTITION BY pstats.object_id ORDER BY pstats.object_id, pstats.partition_number), 'Infinity') AS VARCHAR(100))
  END AS PartitionRange
  ,pstats.partition_number AS PartitionNumber
  ,pstats.row_count AS PartitionRowCount
  ,p.data_compression_desc AS DataCompression
FROM sys.dm_db_partition_stats AS pstats
INNER JOIN sys.partitions AS p ON pstats.partition_id = p.partition_id
INNER JOIN sys.destination_data_spaces AS dds ON pstats.partition_number = dds.destination_id
INNER JOIN sys.data_spaces AS ds ON dds.data_space_id = ds.data_space_id
INNER JOIN sys.partition_schemes AS ps ON dds.partition_scheme_id = ps.data_space_id
INNER JOIN sys.partition_functions AS pf ON ps.function_id = pf.function_id
INNER JOIN sys.indexes AS i ON pstats.object_id = i.object_id AND pstats.index_id = i.index_id AND dds.partition_scheme_id = i.data_space_id AND i.type <= 1 /* Heap or Clustered Index */
INNER JOIN sys.index_columns AS ic ON i.index_id = ic.index_id AND i.object_id = ic.object_id AND ic.partition_ordinal > 0
INNER JOIN sys.columns AS c ON pstats.object_id = c.object_id AND ic.column_id = c.column_id
LEFT JOIN sys.partition_range_values AS prv ON pf.function_id = prv.function_id AND pstats.partition_number = (CASE pf.boundary_value_on_right WHEN 0 THEN prv.boundary_id ELSE (prv.boundary_id+1) END)
WHERE pstats.object_id = OBJECT_ID('Sales.Invoices')
ORDER BY TableName, PartitionNumber;

MS SQL Server-partitioneringsydelse

Vi vil sammenligne den partitionerede og ikke-opdelte tabelydelse for den samme tabel. For at gøre dette skal du bruge nedenstående forespørgsel og aktivere Inkluder faktisk eksekveringsplan.

DECLARE @Dt as date  = '20131231'
SELECT COUNT(InvoiceDate)
  FROM [Sales].[Invoices]
  where InvoiceDate < @Dt

Når vi undersøger udførelsesplanen, finder vi ud af, at den inkluderer egenskaber "Opdelt", "Faktisk antal partitioner" og "Faktisk opdelt adgang".

Den opdelte ejendom angiver, at denne tabel er aktiveret til partition.

Faktisk partitionantal egenskab er det samlede antal partitioner, der læses af SQL Server-motoren.

Faktisk opdelt adgang egenskaben er partitionsnumre vurderet af SQL Server-motoren. SQL Server eliminerer adgangen til andre partitioner, da det kaldes en partitionseliminering og opnår en fordel med hensyn til forespørgselsydeevne.

Se nu på den ikke-opdelte tabeludførelsesplan.

Den største forskel mellem disse to eksekveringsplaner er Antal læste rækker fordi denne egenskab angiver, hvor mange rækker der læses for denne forespørgsel. Som du kan se fra nedenstående komprimeringsdiagram, er værdierne for partitionerede tabel for lave. Af denne grund vil den forbruge en lav IO.

Kør derefter forespørgslen og undersøg udførelsesplanen.

DECLARE @DtBeg as date  = '20140502'
DECLARE @DtEnd as date  = '20140701'

SELECT COUNT(InvoiceDate)
  FROM [Sales].[Invoices]
  where InvoiceDate between @DtBeg and @DtEnd

Låseeskalering på partitionsniveau

Låseeskalering er en mekanisme, der bruges af SQL Server Lock Manager. Det sørger for at låse et niveau af objekter. Når antallet af rækker, der skal låses, stiger, ændrer låseadministratoren et låseobjekt. Dette er hierarkiniveauet for låseeskalering "Række -> Side -> Tabel -> Database". Men i den partitionerede tabel kan vi låse en partition, da det øger samtidighed og ydeevne. Standardniveauet for låseeskalering er "TABEL" i SQL Server.

Udfør forespørgslen ved at bruge nedenstående UPDATE-sætning.

BEGIN TRAN
DECLARE @Dt as date  = '20131221'
UPDATE [Sales].[Invoices] SET CreditNoteReason = 'xxx'   where InvoiceDate < @Dt
SP_LOCK

Det røde felt definerer en eksklusiv lås, der sikrer, at der ikke kan laves flere opdateringer til den samme ressource på samme tid. Det forekommer i tabellen Fakturaer.

Nu vil vi indstille eskaleringstilstanden for Sales.Invoices-tabellen for at automatisere den og køre forespørgslen igen.

ALTER TABLE Sales.Invoices SET (LOCK_ESCALATION = AUTO)

Nu definerer det røde felt den eksklusive indrykningslås, der beskytter anmodede eller erhvervede eksklusive låse på nogle ressourcer lavere i hierarkiet. Kort efter giver dette låseniveau os mulighed for at opdatere eller slette andre partitioner af tabeller. Det betyder, at vi kan starte endnu en opdatering eller indsætte en anden partition af tabellen.

I tidligere indlæg undersøgte vi også spørgsmålet om at skifte mellem tabelopdeling og leverede gennemgangen. Disse oplysninger kan være til hjælp for dig, hvis du behandler disse sager. Se artiklen for mere information.

Referencer

  1. Låsetilstande
  2. Opdelte tabeller og indekser

  1. SQL Server Indsæt eksempel

  2. Hvorfor er udførelsestiden for oracle-lagrede procedurer stærkt forøget afhængigt af, hvordan den udføres?

  3. INSERT INTO eller OPDATERING med to betingelser

  4. Hvordan kan jeg flette kolonnerne fra to tabeller til ét output?