Colonna Identity nell'indice columnstore


9

Ho una tabella IMO estremamente grande (~ 137 milioni di righe) con molti dati ripetuti, molte NULLcolonne e così via.

Sto valutando di esplorarlo utilizzando una tabella con a COLUMNSTORE INDEXe ho una IDENTITYcolonna nella tabella originale, che è la mia unica colonna in cui ogni riga è unica.

Devo lasciare questa colonna fuori o includerla? Ho letto che vuoi includere tutte le righe del tuo tavolo nel COLUMNSTORE INDEXma ho anche letto che i migliori candidati sono colonne con molte righe non univoche.

È solo un cattivo candidato per un COLUMNSTORE INDEX?

Sto usando SQL Server 2012, quindi è un columnstore non cluster. Sto solo esplorando possibili modi migliori per archiviare questi dati. Gli aggiornamenti sono inesistenti, sebbene periodicamente vengano aggiunte nuove righe tramite un processo ELT, quindi presumo che un po 'di lavoro verrebbe svolto lì. Alcune persone raccolgono questi dati e generano enormi rapporti, molte scansioni di righe, a volte il server in una scansione che ci ha costretto a scaricare una copia ogni giorno su un server secondario.


1
La colonna Identity nella tabella originale è anche il tuo indice cluster? In tal caso, SQL Server includerà automaticamente quella colonna in qualsiasi indice columnstore non cluster, anche se non lo richiedi esplicitamente. Ciò è in qualche modo simile al modo in cui le colonne dell'indice cluster verranno incluse in un indice b-tree non cluster, ma i dati verranno archiviati come segmenti di archivio colonne compressi effettivi in ​​questo caso. Vedi dba.stackexchange.com/questions/103722/… per maggiori informazioni.
Geoff Patterson,

137 million rowsè grande ma gestibile. Hai esaminato il partizionamento della tabella e il suo inserimento in diversi filegroup? L'indice columnsstore in sql 2012 non è scrivibile, quindi si verificano problemi: è necessario rilasciarlo e ricrearlo. Non sto dicendo che la volontà di columnstore è negativa, ma è meglio esplorare anche altre opzioni.
Kin Shah,

Risposte:


11

Le colonne di identità non sono veramente compresse negli indici Columnstore in SQL Server 2012 o in SQL Server 2014. Tutto dipenderà veramente dal carico di lavoro che si sta verificando. Se il tuo carico di lavoro includerà la colonna identità, puoi trarre vantaggio dall'eliminazione del segmento.

Dal punto di vista della compressione - Columnstore ti fornirà una compressione migliore rispetto alla pagina in genere. Tipicamente. Si prega di testarlo prima di passare alla produzione.

Il tuo problema più grande in SQL Server 2012 sarà un'implementazione molto debole della modalità batch e non puoi farci nulla.


7
Benvenuto Niko !!!
Aaron Bertrand

3

Non ho potuto resistere a unirmi a Niko con un'altra risposta (benvenuto, Niko!). In generale, sono d'accordo con Niko sul fatto che le limitazioni della modalità batch in SQL 2012 (se Niko non si collegherà al suo blog, lo farò :)) potrebbero essere una delle principali preoccupazioni. Ma se riesci a convivere con quelli e hai il pieno controllo su ogni query che stai scrivendo sulla tabella per esaminarla attentamente, columnstore potrebbe funzionare per te in SQL 2012.

Per quanto riguarda le tue domande specifiche sulla colonna identità, ho scoperto che la colonna identità si comprime molto bene e consiglio vivamente di includerla nel tuo indice columnstore in qualsiasi test iniziale. (Nota che se la colonna identità è anche l'indice cluster del tuo b-tree, sarà automaticamente inclusa nel tuo indice columnstore non cluster .)

Per riferimento, ecco le dimensioni che ho osservato per ~ 10MM righe di dati della colonna identità. Il columnstore caricato per l'eliminazione ottimale del segmento viene compresso a 26 MB (rispetto a 113 MB per la PAGEcompressione della tabella del rowstore) e anche il columnstore creato su un b-tree ordinato casualmente è di soli 40 MB. Questo dimostra un enorme vantaggio in termini di compressione, anche rispetto alla migliore compressione b-tree che SQL ha da offrire e anche se non ti preoccupi di allineare i tuoi dati per l'eliminazione ottimale del segmento (cosa che faresti prima creando un b-tree e poi costruendo il tuo columnstore con MAXDOP1).

inserisci qui la descrizione dell'immagine

Ecco lo script completo che ho usato nel caso in cui desideri giocare:

-- Confirm SQL version
SELECT @@version
--Microsoft SQL Server 2012 - 11.0.5613.0 (X64) 
--  May  4 2015 19:05:02 
--  Copyright (c) Microsoft Corporation
--  Enterprise Edition: Core-based Licensing (64-bit) on Windows NT 6.3 <X64> (Build 9600: )


-- Create a columnstore table with identity column that is the primary key
-- This will yield 10 columnstore segments @ 1048576 rows each
SELECT i = IDENTITY(int, 1, 1), ROW_NUMBER() OVER (ORDER BY randGuid) as randCol
INTO #testIdentityCompression_sortedColumnstore
FROM (
    SELECT TOP 10485760 ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS randI, NEWID() AS randGuid
    FROM master..spt_values v1
    CROSS JOIN master..spt_values v2
    CROSS JOIN master..spt_values v3
) r
ORDER BY r.randI
GO
ALTER TABLE #testIdentityCompression_sortedColumnstore
ADD PRIMARY KEY (i)
GO
-- Load using a pre-ordered b-tree and one thread for optimal segment elimination
-- See http://www.nikoport.com/2014/04/16/clustered-columnstore-indexes-part-29-data-loading-for-better-segment-elimination/
CREATE NONCLUSTERED COLUMNSTORE INDEX cs_#testIdentityCompression_sortedColumnstore ON #testIdentityCompression_sortedColumnstore (i) WITH (MAXDOP = 1)
GO

-- Create another table with the same data, but randomly ordered
SELECT *
INTO #testIdentityCompression_randomOrderColumnstore
FROM #testIdentityCompression_sortedColumnstore
GO
ALTER TABLE #testIdentityCompression_randomOrderColumnstore
ADD UNIQUE CLUSTERED (randCol)
GO
CREATE NONCLUSTERED COLUMNSTORE INDEX cs_#testIdentityCompression_randomOrderColumnstore ON #testIdentityCompression_randomOrderColumnstore (i) WITH (MAXDOP = 1)
GO

-- Create a b-tree with the identity column data and no compression
-- Note that we copy over only the identity column since we'll be looking at the total size of the b-tree index
-- If anything, this gives an unfair "advantage" to the rowstore-page-compressed version since more
-- rows fit on a page and page compression rates should be better without the "randCol" column.
SELECT i
INTO #testIdentityCompression_uncompressedRowstore
FROM #testIdentityCompression_sortedColumnstore
GO
ALTER TABLE #testIdentityCompression_uncompressedRowstore
ADD PRIMARY KEY (i)
GO

-- Create a b-tree with the identity column and page compression
SELECT i
INTO #testIdentityCompression_compressedRowstore
FROM #testIdentityCompression_sortedColumnstore
GO
ALTER TABLE #testIdentityCompression_compressedRowstore
ADD PRIMARY KEY (i)
WITH (DATA_COMPRESSION = PAGE)
GO

-- Compare all the sizes!
SELECT OBJECT_NAME(p.object_id, 2) AS tableName, COUNT(*) AS num_segments, SUM(on_disk_size / (1024.*1024.)) as size_mb
FROM tempdb.sys.partitions p
JOIN tempdb.sys.column_store_segments s
    ON s.partition_id = p.partition_id
    AND s.column_id = 1
WHERE p.object_id IN (OBJECT_ID('tempdb..#testIdentityCompression_sortedColumnstore'),OBJECT_ID('tempdb..#testIdentityCompression_randomOrderColumnstore'))
GROUP BY p.object_id
UNION ALL
SELECT OBJECT_NAME(p.object_id, 2) AS tableName
    , NULL AS num_segments
    , (a.total_pages*8.0) / (1024.0) as size_mb
FROM tempdb.sys.partitions p
JOIN tempdb.sys.allocation_units a
    ON a.container_id = p.partition_id
WHERE p.object_id IN (OBJECT_ID('tempdb..#testIdentityCompression_compressedRowstore'),OBJECT_ID('tempdb..#testIdentityCompression_uncompressedRowstore'))
ORDER BY 3 ASC
GO

Grazie per tutte le ottime risposte, in questo momento ho deciso di rimanere in attesa fino a quando non riuscirò ad accedere almeno al server sql 2014. Stiamo intensificando i nostri aggiornamenti, quindi spero nel prossimo anno o così potremo farlo.
Don
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.