1. 1. TworzenieColumnStore.sql
-- to ćwiczenie możemy wykonać w kontekście dowolnej bazy danych, tutaj
AdventureWorks2012
USE AdventureWorks2012
GO
--stworzenie tabeli
CREATETABLE dbo.ColumnStoreIndex(
Column1 INTIDENTITY,
Column2 VARCHAR(50),
Column3 DATETIME,
Column4 NUMERIC(16,2)
)
-- Stworzenie indeksu klastrowego
CREATECLUSTEREDINDEX IX_Column1 ON dbo.ColumnStoreIndex(Column1)
-- stworzenie indeksu nieklastrowego COLUMNSTORE
CREATENONCLUSTERED COLUMNSTORE INDEX IX_CS_C2_C3_C4
ON dbo.ColumnStoreIndex(Column2,Column3,Column4)
--czyszczenie bazy danych
DROPINDEX IX_CS_C2_C3_C4 ON dbo.ColumnStoreIndex
GO
DROPTABLE dbo.ColumnStoreIndex
GO
2. UpdateTabeli.sql
USE AdventureWorks2012
GO
--stworzenie tabeli
CREATETABLE dbo.ColumnStore(
Column1 INTIDENTITY,
Column2 VARCHAR(50),
Column3 DATETIME,
Column4 NUMERIC(16,2)
)
-- stworzenie indeksu klastrowego
CREATECLUSTEREDINDEX IX_Column1 ON dbo.ColumnStore(Column1)
-- stworzenie indeksu nieklastrowego COLUMNSTORE
CREATENONCLUSTERED COLUMNSTORE INDEX IX_CS_C2_C3_C4
ON dbo.ColumnStore(Column2,Column3,Column4)
--próba wstawienia rekordu (błąd)
Insertinto dbo.ColumnStore Values('Col2 Val1',GETDATE(),10.23)
-- Wyłączenie indeksu columnstore zanim wykonany instrukcję INSERT
ALTERINDEX IX_CS_C2_C3_C4 ON dbo.ColumnStore DISABLE;
--wstawienie rekordu
INSERTINTO dbo.ColumnStore VALUES('Col2 Val1',GETDATE(),10.23)
2. INSERTINTO dbo.ColumnStore VALUES('Col2 Val2',GETDATE(),10.24)
-- przebudowa indeksu columnstore co wykonaniu instrukcji INSERT
ALTERINDEX IX_CS_C2_C3_C4 ON dbo.ColumnStore REBUILD;
--czyszczenie bazy danych
DROPINDEX IX_CS_C2_C3_C4 ON dbo.ColumnStore
GO
DROPTABLE dbo.ColumnStore
GO
---------------
--Alternatywnie my możemy najpierw stworzyć tabelę, potem dodać rekord i
potem dopiero stworzyć indeks columnstore
--stworzenie tabeli
CREATETABLE dbo.ColumnStore1(
Column1 INTIDENTITY,
Column2 VARCHAR(50),
Column3 DATETIME,
Column4 NUMERIC(16,2)
)
--Wstawienie rekordu
INSERTINTO dbo.ColumnStore1 VALUES('Col2 Val1',GETDATE(),10.23)
INSERTINTO dbo.ColumnStore1 VALUES('Col2 Val2',GETDATE(),10.24)
--stworzenie indeksów
-- stworzenie indeksu klastrowego
CREATECLUSTEREDINDEX IX_Column1 ON dbo.ColumnStore1(Column1)
-- stworzenie indeksu nieklastrowego COLUMNSTORE
CREATENONCLUSTERED COLUMNSTORE INDEX IX_CS_C2_C3_C4
ON dbo.ColumnStore1(Column2,Column3,Column4)
--ten sposób zadziała tylko za pierwszym razem (wykonanie insertów przed
stworzeniem indeksu columnstore).
--próba wykonania tej instrukcji, spowoduje wyżwietlenie błędu
UPDATE dbo.ColumnStore1
SET Column2 ='Updated Value'
WHERE Column1 = 1
-- aby można wykonać tą aktualizację należy wyłączyć indeks columnstore
zanim spróbujemy wykonać UPDATE
ALTERINDEX IX_CS_C2_C3_C4 ON dbo.ColumnStore1 DISABLE;
UPDATE dbo.ColumnStore1
SET Column2 ='Updated Value'
WHERE Column1 = 1
-- przebudowa indeksu columnstore jak wykona się instrukcja INSERT
ALTERINDEX IX_CS_C2_C3_C4 ON dbo.ColumnStore1 REBUILD;
SELECT*FROM dbo.ColumnStore1
-- Czyszczenie bazy danych
DROPINDEX IX_CS_C2_C3_C4 ON dbo.ColumnStore1
GO
DROPTABLE dbo.ColumnStore1
GO
3. 3. Ograniczenia.sql
--1. Nie można stworzyć klastrowego indeksu ColumnStore
USE AdventureWorks2012
GO
--stworzenie tabeli
CREATETABLE dbo.ColumnStoreIndex(
Column1 INTIDENTITY,
Column2 VARCHAR(50),
Column3 DATETIME,
Column4 NUMERIC(16,2)
)
-- próba stworzenia indeksu klastrowego COLUMNSTORE
CREATECLUSTERED COLUMNSTORE INDEX IX_CS_C2_C3_C4
ON dbo.ColumnStoreIndex(Column2,Column3,Column4)
-- Czyszczenie bazy danych
DROPTABLE dbo.ColumnStoreIndex
--2. Nie można stworzyć nieklastrowego indeksu COLUMNSTORE z opcją INCLUDE
USE AdventureWorks2012
GO
--stworzenie tabeli
CREATETABLE dbo.ColumnStoreIndex(
Column1 INTIDENTITY,
Column2 VARCHAR(50),
Column3 DATETIME,
Column4 NUMERIC(16,2)
)
-- próba stworzenia nieklastrowanego indeksu COLUMNSTORE
CREATENONCLUSTERED COLUMNSTORE INDEX IX_CS_C2
ON dbo.ColumnStoreIndex(Column2)
INCLUDE (Column1 ,Column3 ,Column4 )
GO
-- Czyszczenie bazy danych
DROPTABLE dbo.ColumnStoreIndex
--3.Nie można stworzyć indeksu ColumnStore na kolumnach wyliczanych
(computed)
--stworzenie tabeli
CREATETABLE dbo.ColumnStoreIndex(
Column1 INTIDENTITY,
Column2 VARCHAR(50),
Column3 DATETIME,
Column4 INT,
Column5 AS (Column1+Column4)-- kolumna wyliczana
)
4. -- stworzenie nieklastrowego indeksu COLUMNSTORE
CREATENONCLUSTERED COLUMNSTORE INDEX IX_CS_C2
ON dbo.ColumnStoreIndex(Column5)
-- Czyszczenie bazy danych
DROPTABLE dbo.ColumnStoreIndex
--4. Nie można stworzyć wielu indeksów ColumnStore
--stworzenie tabeli
CREATETABLE dbo.ColumnStoreIndex(
Column1 INTIDENTITY,
Column2 VARCHAR(50),
Column3 DATETIME,
Column4 NUMERIC(16,2)
)
-- Próba stworzenia kliku indeksów COLUMNSTORE
CREATENONCLUSTERED COLUMNSTORE INDEX IX_CS_C2
ON dbo.ColumnStoreIndex(Column2)
CREATENONCLUSTERED COLUMNSTORE INDEX IX_CS_C3
ON dbo.ColumnStoreIndex(Column3)
-- Czyszczenie bazy danych
DROPTABLE dbo.ColumnStoreIndex
4. TestWydajności.sql
USE AdventureWorks2012
GO
-- stworzenie nowej tabeli
CREATETABLE dbo.TestColumnStoreIndexes(
[SalesOrderID] [int] NOTNULL,
[SalesOrderDetailID] [int] NOTNULL,
[CarrierTrackingNumber] [nvarchar](25)NULL,
[OrderQty] [smallint] NOTNULL,
[ProductID] [int] NOTNULL,
[SpecialOfferID] [int] NOTNULL,
[UnitPrice] [money] NOTNULL,
[UnitPriceDiscount] [money] NOTNULL,
[LineTotal] [numeric](38, 6)NOTNULL,
[rowguid] [uniqueidentifier] NOTNULL,
[ModifiedDate] [datetime] NOTNULL
)ON [PRIMARY]
GO
-- stworzenie indeksu klastrowego
CREATECLUSTEREDINDEX CL_TestColumnStoreIndexes ON
dbo.TestColumnStoreIndexes
( [SalesOrderDetailID])
GO
-- stworzenie tabeli do testów
-- To zapytanie może się wykonywać dożć długo
5. INSERTINTO dbo.TestColumnStoreIndexes
SELECT S1.*
FROM Sales.SalesOrderDetail S1
GO 100
-- wstawi mi 12 131 700 rekordów
-- select * FROM dbo.TestColumnStoreIndexes
-- pierwszy test wydajnożciowy
-- wykorzystanie SET STATISTICS IO ON dla zmierzenia ilożci operacji IO,
których potrzeba do wykonania zapytania.
-- w pierwszym teżcie uruchomimy zapytanie, które będzie używało zwykłych
indeksów.
-- należy zanotować użycie operacji IO w zapytaniu
-- potem sprawdzimy to samo przy użyciu indeksów ColumnStore i znowu
zmierzenie operacji IO
-- Test wydajnożci
-- Porównanie zwykłego indeksu z indeksem ColumnStore
USE AdventureWorks2012
GO
SETSTATISTICSIOON
GO
--włączenie Actual Execution Plan
-- Select na tabeli ze zwykłym indeksem nieklastrowym
SELECT ProductID,SUM(UnitPrice) SumUnitPrice,AVG(UnitPrice) AvgUnitPrice,
SUM(OrderQty) SumOrderQty,AVG(OrderQty) AvgOrderQty
FROM dbo.TestColumnStoreIndexes
GROUPBY ProductID
ORDERBY ProductID
GO
--Table 'dbo.TestColumnStoreIndexes'. Scan count 1, logical reads 345590,
physical reads 0, read-ahead reads 0.
--stworzenie indeksu ColumnStore
CREATENONCLUSTERED COLUMNSTORE INDEX IX_TestColumnStoreIndexes
ON TestColumnStoreIndexes
(UnitPrice, OrderQty, ProductID)
GO
-- Select na tabeli z indeksem Columnstore
SELECT ProductID,SUM(UnitPrice) SumUnitPrice,AVG(UnitPrice) AvgUnitPrice,
SUM(OrderQty) SumOrderQty,AVG(OrderQty) AvgOrderQty
FROM [dbo].TestColumnStoreIndexes
GROUPBY ProductID
ORDERBY ProductID
GO
-- wydajność radykalnie wzrosła po stworzeniu indeksu ColumnStore Index.
-- Ilożć stron, które zapytanie miało odczytać została drastycznie
zredukowana
--jako że kolumny, które są potrzebne do zapytania są przechowywane na tej
samej stronie i zapytanie nie musi przeszukiwac każdej
-- pojedynczej kolumny, aby odczytać te strony.
--jeżli włączymy execution plan i porównamy, możemy zobaczyć, że wydajność
indeksu ColumnStore jest dużo lepsza niż zwykłego indeksu
--nieklastrowanego w tym przypadku.
-- Czyszczenie bazy danych
DROPINDEX [IX_TestColumnStoreIndexes] ON dbo.TestColumnStoreIndexes
GO
TRUNCATETABLE dbo.TestColumnStoreIndexes
7. [OrderDate] datetimeNULL,
[DueDate] datetimeNULL,
[ShipDate] datetimeNULL
)ON ByOrderDateMonthRange(OrderDateKey);
GO
-- skopiowanie danych z tabeli FactResellerSales do nowej tabeli
INSERTINTO dbo.FactResellerSalesPtnd WITH(TABLOCK)
SELECT*FROM AdventureWorksDW2012.dbo.FactResellerSales;
GO
-- stworzenie indeksu columnstore
CREATENONCLUSTERED COLUMNSTORE INDEX [csindx_FactResellerSalesPtnd]
ON [FactResellerSalesPtnd]
(
[ProductKey],
[OrderDateKey],
[DueDateKey],
[ShipDateKey],
[ResellerKey],
[EmployeeKey],
[PromotionKey],
[CurrencyKey],
[SalesTerritoryKey],
[SalesOrderNumber],
[SalesOrderLineNumber],
[RevisionNumber],
[OrderQuantity],
[UnitPrice],
[ExtendedAmount],
[UnitPriceDiscountPct],
[DiscountAmount],
[ProductStandardCost],
[TotalProductCost],
[SalesAmount],
[TaxAmt],
[Freight],
[CarrierTrackingNumber],
[CustomerPONumber]
);
--wykonanie następującego zapytania (podejrzenie planu wykonania)
SELECT SalesTerritoryKey,SUM(ExtendedAmount)AS SalesByTerritory
FROM FactResellerSalesPtnd
GROUPBY SalesTerritoryKey;
--możemy zauważyć, że actual i estimated execution mode jest Row (linie 3 i
4 na liżcie Properties indeksu).
--Row execution mode został wybrany ponieważ tabela nie jest wystarczająco
duża, aby wywołać batch execution mode.
--możemy użyć nieudokumentowanych opcji ROWCOUNT (dla 10 mln wierszy) i
PAGECOUNT (dla 1 mln stron) do instrukcji UPDATE STATISTICS,
--aby zasymulować, jakby się to wykonało na większej tabeli
UPDATESTATISTICS FactResellerSalesPtnd WITHROWCOUNT= 10000000,PAGECOUNT=
1000000
--usunięcie z cache'u starego planu wykonania
8. DBCC FREEPROCCACHE
--wykonanie jeszcze raz tego zapytania
SELECT SalesTerritoryKey,SUM(ExtendedAmount)AS SalesByTerritory
FROM FactResellerSalesPtnd
GROUPBY SalesTerritoryKey;
--tym razem we włażciwożciach Columnstore Index Scan możemy zobaczyć, że
wykonał to używać the batch execution mode
--możemy także użyć nowego hinta IGNORE_NONCLUSTERED_COLUMNSTORE_INDEX do
wyłaczenia użycia indeksu columnstore.
SELECT SalesTerritoryKey,SUM(ExtendedAmount)AS SalesByTerritory
FROM FactResellerSalesPtnd
GROUPBY SalesTerritoryKey
OPTION (IGNORE_NONCLUSTERED_COLUMNSTORE_INDEX);
-- teraz plan wykonania pokazuje Nam skan tabeli FactResellerSalesPtnd, bez
użycia indeksu columnstore.
-- usunięcie tabeli
DROPTABLE FactResellerSalesPtnd
GO
DROPPARTITION SCHEME ByOrderDateMonthRange
GO
DROPPARTITIONFUNCTION ByOrderDateMonthPF
GO