Sql-server – Adding new columns to Table with Clustured Columnstore Index

columnstoresql serversql-server-2016

I have a daily facts table 'FactsTable1' with 240 columns on which I am exploring 'Clustured Columnstore Index'(CCI).

I want to know,

  • What happens when I add another ~50 columns to the table?
  • Will they automatically added to CCI? Or I have to rebuild CCI once
    again?
  • What should be the best way to handle such conditions?
  • If I have to rebuild index to make new columns to be part of CCI
    then what will happen if I dont rebuild? How will it affect my query
    performance?

Additional information :

  • FactsTable1 contains 400000+ rows & 240 columns
  • Its partitioned on date column
  • It is heavily queried for analytic data.
  • @@version : Microsoft SQL Server 2016 (RTM) – 13.0.1601.5 (X64)

Best Answer

What happens when I add another 50 columns to the table?

These columns will be added to the table with NULL values if you have not specified a default value. If you have added a default value, the compressed rowgroups will stay as they are and no updates will be done.

Will they automatically be added to the CCI?

Yes

What should be the best way to handle such conditions?

If you are going to update all the values of the new columns, you will get a lot of compressed row groups with more deleted rows and open delta stores (heaps), when doing a massive update the tuple mover will kick in and turn these delta stores into compressed segments if they are marked as closed (size 1 000 000 rows). To get rid of the compressed segments with only a few rows left you will have to do a REORGANIZE statement

Additional Information

--> You need 1 000 000 rows at least to get CCI to work well, otherwise you will be stuck in your heap delta store. (you only have 400 000)

This will require you to do a rebuild or reorganize of the index to get all rows into a compressed segment

ALTER INDEX idx_cci_target ON cci_target REORGANIZE WITH (COMPRESS_ALL_ROW_GROUPS = ON);

You should also upgrade you SQL Server 2016 to SP1

Try this

Because you do not have so many rows in your Fact table, it might be better to use the NCCI trick. You can create an empty filtered nonclustered columnstore index on your table. This will have a zero cost on your table, but will trigger the batch mode executions plans which will give you a lot of gains for analytical queries.

CREATE NCCI_TEST on TESTABLE (ALL COLUMNS)
WHERE ID = -1 and ID = -2

Examples

CREATE TABLE dbo.test
(
Bla datetime,
blabla varchar(200)
)
GO
CREATE CLUSTERED COLUMNSTORE INDEX CCI_TEST on DBO.TEST
GO

And then insert some rows

INSERT INTO dbo.test
select DATEADD(day, (ABS(CHECKSUM(NEWID())) % 65530), 0),cast(ABS(CHECKSUM(NEWID())) as varchar)
GO 10000

insert into dbo.test
select * from dbo.test
GO 5

If you then go and check your columnstore elements

select * from sys.column_store_row_groups

RowstoreElements

You see that you now have a delta store, which means this is a heap table without indexes.

If you then rebuild your index with the compress all rowgroups

ALTER INDEX CCI_TEST on DBO.TEST REORGANIZE WITH (COMPRESS_ALL_ROW_GROUPS = ON)

Compressed

The tombstone elements are the previous deltastore/compressed segments which still linger they will be removed after about 5 minutes

You now have your columnstore compression (which will avoid locking issues)

If we now add a new column

alter table dbo.test add nondefaultvalue varchar(20)

And we check the row groups again

StillCompressed

you still have the good layout of your row groups.

If we add another column with a default value and check the rowgroups

alter table dbo.test add defaultvalue varchar(20) not null default('DEFAULT')

Rowgroups still

If you then however decide to update those values.

UPDATE dbo.test 
set nondefaultvalue = 'DEFAULT'

Things change

OpenDeltastore

We no longer have a compressed segment we can use. If we then try to reorganize this index

ALTER INDEX CCI_TEST on DBO.TEST REORGANIZE

Reorganizeafterupdate

We get our open delta store again, which will cause locking. We can however get it back to a compressed segment by issuing the following command we saw previously

ALTER INDEX CCI_TEST on DBO.TEST REORGANIZE WITH (COMPRESS_ALL_ROW_GROUPS = ON)

recompressed

Now we have to good columnstore segment again.

So in your case you will have to do a reorganize with compress all row groups, to get it working fine. This should not take long on a table with only 400 000 rows but it is necessary to avoid locking.

If you do bulk inserts the story changes again, but you will have to do 100 000 rows at once to get everything straight into a compressed segment.

Dictionaries

When adding another column a new dictionary will be made for your columnstore index (sort of mapping to the column elements inside your columnstore segments).

select * from sys.column_store_dictionaries

alter table dbo.test add defaultvalue2 varchar(20) not null default('DEFAULT')

select * from sys.column_store_dictionaries

Dictionaries

For more information I suggest you go to http://www.nikoport.com/ he has all the extra information you need on columnstore on his blog.