Posso spostare le righe tra le partizioni aggiornando la chiave di partizione?


17

Penserei che questa sarebbe una domanda abbastanza semplice, ma in realtà ho avuto difficoltà a trovare una risposta per questo.

La domanda: puoi spostare righe di dati all'interno di una tabella partizionata da una partizione all'altra semplicemente aggiornando la colonna della partizione in modo che attraversi il limite della partizione?

Ad esempio, se ho una tabella con una chiave di partizione:

CREATE TABLE SampleTable
(
    SampleID INT PRIMARY KEY,
    SampleResults VARCHAR(100) NOT NULL,
)

Con la funzione di partizione associata alla chiave primaria:

CREATE PARTITION FUNCTION MyPartitionFunc (INT) AS
RANGE LEFT FOR VALUES (10000, 20000);

Posso spostare una riga dalla prima partizione alla terza partizione modificando il SampleID da 1 a (diciamo) 500.000?

Nota: lo taggo come server SQL 2005 e 2008, poiché entrambi supportano il partizionamento. Lo gestiscono in modo diverso?

Risposte:


14

Non ho un server 2005 con cui provare. Il 2008, tuttavia, sembra gestirlo come previsto:

USE [Test]
GO
CREATE TABLE [IDRanges](
    [ID] [int] NOT NULL
)
GO

CREATE PARTITION FUNCTION IDRange1 (int)
AS RANGE LEFT FOR VALUES (10) ;
GO
--Add one record to each partition
INSERT INTO IDRanges ([ID]) VALUES (17)
INSERT INTO IDRanges ([ID]) VALUES (7)
GO
--Verify records in partition
SELECT $PARTITION.IDRange1([ID]) AS Partition, COUNT(*) AS [COUNT] 
FROM IDRanges
GROUP BY $PARTITION.IDRange1([ID]) 
ORDER BY Partition ;
GO
--Move row between partitions
UPDATE IDRanges
SET [ID] = 8 WHERE [ID] = 17
GO
--Verify records in partition
SELECT $PARTITION.IDRange1([ID]) AS Partition, COUNT(*) AS [COUNT] 
FROM IDRanges
GROUP BY $PARTITION.IDRange1([ID]) 
ORDER BY Partition ;

Dovresti vedere un record in ogni partizione prima dell'aggiornamento ed entrambi i record nella prima partizione in seguito.


1
è una risposta ben fatta!
Marian,

Questo viene eseguito come descritto anche in SQL Server 2005
Ben Brocka,

-1 Questo non verifica lo scenario. $PARTITIONcalcola solo il numero di partizione in base all'input; in realtà non verifica dove vive fisicamente la riga.
Jon Seigel,

9

Per verificarlo, l'esperimento deve effettivamente partizionare la tabella. Vedi http://www.kodyaz.com/articles/how-to-partition-table-non-partitioned-table-sql-server-2008.aspx

L'interrogazione della funzione di partizionamento indica semplicemente cosa dice la funzione di partizionamento. Non dice dove sono archiviati i dati. È possibile impostare una funzione di partizionamento ed eseguirla senza effettivamente partizionare una tabella, come è già stato dimostrato qui.

Per partizionare la tabella, è inoltre necessario creare gruppi di file e uno schema di partizionamento che utilizza la funzione di partizionamento per assegnare i risultati della funzione ai gruppi di file. Quindi devi inserire una chiave cluster sulla tabella che utilizza quello schema di partizionamento.

Imposta il partizionamento

Non sono un esperto di SQL da riga di comando. Ho usato l'interfaccia SSMS per impostare i gruppi di file pfg1 (con un file pf1) e pfg2 (con un file pf2). Quindi ho dichiarato la funzione e lo schema di partizionamento:

CREATE PARTITION FUNCTION IDRange1 (int)
AS RANGE LEFT FOR VALUES (10) ;
GO

CREATE PARTITION SCHEME ps_IDRange1
AS PARTITION IDRange1
TO (pfg1, pfg2)
GO

Creare la tabella e l'indice cluster

CREATE TABLE [IDRanges](
    [ID] [int] NOT NULL
)
GO

CREATE CLUSTERED INDEX PK_IDRanges
ON dbo.IDRanges(id) ON ps_IDRange1 (ID)
GO

Dopo aver fatto ciò, quando si esegue una query su sys.partitions (I have 2005), si vede che la tabella ora ha due partizioni invece di una sola per la tabella. Ciò indica che abbiamo implementato completamente il partizionamento per questa tabella.

select * from sys.partitions where object_id = object_id('IDRanges')
ID_partizione_ID oggetto_id indice_partizione file hobt_id
-------------------- ----------- ----------- -------- -------- -------------------- --------------------
72057597780295680 770674389 1 1 72057597780295680 0
72057597780361216 770674389 1 2 72057597780361216 0

Ora che abbiamo due partizioni (con un numero di righe per ciascuna), possiamo condurre un esperimento.

Inserisci le righe

INSERT INTO IDRanges ([ID]) VALUES (17)
INSERT INTO IDRanges ([ID]) VALUES (7)

Controlla le partizioni sys.per vedere cosa è successo.

select * from sys.partitions where object_id = object_id('IDRanges')
ID_partizione_ID oggetto_id indice_partizione file hobt_id
-------------------- ----------- ----------- -------- -------- -------------------- --------------------
72057597780295680 770674389 1 1 72057597780295680 1
72057597780361216 770674389 1 2 72057597780361216 1

Sì. Una riga in ogni partizione.

Sposta una riga.

UPDATE IDRanges
SET [ID] = 8 WHERE [ID] = 17

Controlla le partizioni

select * from sys.partitions where object_id = object_id('IDRanges')
ID_partizione_ID oggetto_id indice_partizione file hobt_id
-------------------- ----------- ----------- -------- -------- -------------------- --------------------
72057597780295680 770674389 1 1 72057597780295680 2
72057597780361216 770674389 1 2 72057597780361216 0

La prima partizione ora ha due righe invece di 1 e la seconda partizione ha zero righe anziché due.

Penso che ciò confermi che la riga è stata spostata automaticamente a seguito della modifica della chiave cluster in una tabella partizionata.


1
+1 per la prima risposta a questa domanda che verifica effettivamente lo scenario. Benvenuto in DBA.SE!
Jon Seigel,

-1 Puoi indicarmi i documenti MSDN che supportano i tuoi requisiti per partizionare "completamente" una tabella? In particolare la necessità di gruppi di file separati e un indice cluster?
Kenneth,

-2

Non penso che la risposta sia corretta. Quando si utilizza il valore

 $PARTITION.IDRange1([ID]) AS Partition

stai semplicemente ricalcolando quale dovrebbe essere la partizione, non dove si trova attualmente il record.

Dovresti usare:

select * from sys.partitions where object_id = object_id('IDRanges')

Nei miei test su sql 2005 il valore cambia ma il record rimane nella stessa partizione. Questo probabilmente guasterà con le statistiche e l'ottimizzatore poiché verrà eseguito in una modalità multi-thread in attesa di una partizione in un intervallo specifico. Sarà anche completamente sbagliato quando si tenta di utilizzare l'eliminazione della partizione per interrogare solo la partizione pertinente. Penso che sia necessario eliminare e reinserire ogni record per farli spostare.


2
La ricerca $partition qui suggerisce che la risposta accettata è corretta. Come stai confermando che il record rimane nella stessa partizione dopo che è stato aggiornato?
Nick Chammas,

Il primo punto è vero, ma la conclusione che la riga non si sposta è falsa - presumibilmente c'è qualcosa di sbagliato nel test che è stato eseguito.
Jon Seigel,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.