Feeds:
Posts
Comments

Archive for the ‘Performance’ Category

Columnstore index is one of the nice features introduced in SQL Server 2012. It improves the performance more times than the normal query but on the other hand it has some limitations as well, and one of the limitation is that you cannot create a CLUSTERED Columnstore index.

Let me demonstrate it in SQL Server 2012.

USE tempdb
GO
CREATE TABLE tbl_Product_Master
(
[Product ID] INT,
[Product Name] NVARCHAR(100),
[Model] INT
)
GO
CREATE CLUSTERED COLUMNSTORE INDEX
[IX_tbl_Product_Master_ColumnStore]
ON [tbl_Product_Master] ([Product ID])
GO
--OUTPUT

Msg 35338, Level 15, State 1, Line 3
Clustered columnstore index is not supported.

Ooopps…… I am unable to create it in SQL Server 2012.

The above limitation has been eliminated in SQL Server 2014 and you can add the CLUSTERED COLUMNSTORE INDEX in the table.

Let me demonstrate the same example in SQL Server 2014.


USE tempdb
GO
CREATE TABLE tbl_Product_Master
(
[Product ID] INT,
[Product Name] NVARCHAR(100),
[Model] INT
)
GO

CREATE CLUSTERED COLUMNSTORE INDEX
[IX_tbl_Product_Master_ColumnStore]
ON [tbl_Product_Master]
GO
--OUTPUT

Command(s) completed successfully.

Lets check whether the index has been created successfully or not.

columnstoreindexcusteredindex1.1

The result is evident above, in SQL 2014.

Let me know if you explore the other nice enhancements of SQL Server 2014.

Read Full Post »

Scalability and performance is one of the core areas of SQL Server that we should take care of. Today, I was searching for something on MSDN and came across an exciting page (Scalability and Performance Enhancements). In this page, I found few Scalability and Performance Enhancements shipped with SQL Server 2012. The exciting topic was flashing & encouraging me to test was FILESTREAM Filegroups Can Contain Multiple Files
The purpose of this enhancement is to increase the performance of your database because now you can place multiple files in multiple drives under one file group.

Let me create a sample to explain how you can contain multiple files in a single file group.

CREATE DATABASE [Personal_DB]
CONTAINMENT = NONE
ON PRIMARY
(
NAME = N'Personal_DB',
FILENAME = N'C:\Data\Personal_DB.mdf',
SIZE = 100MB,
MAXSIZE = UNLIMITED,
FILEGROWTH = 1MB
),
FILEGROUP [FS] CONTAINS FILESTREAM DEFAULT
(
NAME = N'Music',
FILENAME = N'C:\Data\Music',
MAXSIZE = UNLIMITED
),
(
NAME = N'Videos',
FILENAME = N'C:\Data\Videos',
MAXSIZE = 100MB
)
LOG ON
(
NAME = N'Personal_DB_log',
FILENAME = N'C:\Data\Personal_DB_log.ldf',
SIZE = 100MB,
MAXSIZE = 1GB,
FILEGROWTH = 1MB
)
GO

Do share with me if you implemented this enhancement in the real world.

Read Full Post »

In my previous article, I wrote a script to disable all index of any particular database or you can disable any particular category (NONCLUSTERED COLUMNSTORE INDEXES ,HEAP, CLUSTERED INDEX, NONCLUSTERED INDEX, XML INDEX, SPATIAL INDEX) index as well. Given below is the script that can rebuild (enable) all indexes of any particular database or can rebuild (enable) any particular category index as well.

CREATE PROCEDURE dbo.[REBUILD_ALL_INDEXES_PROC]
@Type int
AS
BEGIN
DECLARE @Schema_TableName nvarchar(max)
DECLARE @Index_Type int
DECLARE @String varchar(max)
DECLARE @Fillfactor VARCHAR(3)
SET @Fillfactor=80

DECLARE IndexCursor CURSOR FOR

Select scma.[name] + '.'
+ Quotename(tbl.name) as [Schema_TableName]
,i.type
from sys.tables AS tbl
INNER JOIN sys.indexes AS i
ON (i.index_id > 0 AND i.is_hypothetical = 0)
AND (i.object_id=tbl.object_id)
INNER JOIN sys.schemas AS scma
ON tbl.schema_id=scma.schema_id
Where tbl.type='U' AND ((1=(CASE
WHEN @Type is Null THEN 1 ELSE 0 END)
OR i.type = @Type))
Order By scma.[name] + '.' + tbl.name

OPEN IndexCursor
FETCH NEXT FROM IndexCursor INTO @Schema_TableName,@Index_Type

WHILE @@FETCH_STATUS = 0
BEGIN
IF @Index_Type=6
BEGIN
--To rebuild columnstore index only
SET @String = 'ALTER INDEX ALL ON ' + @Schema_TableName +
' REBUILD;'
END
ELSE
BEGIN
--To rebuild other indexes
SET @String = 'ALTER INDEX ALL ON ' + @Schema_TableName +
' REBUILD WITH (FILLFACTOR = ' + @Fillfactor + '
, SORT_IN_TEMPDB = ON, STATISTICS_NORECOMPUTE = ON);'
END
Print @String
EXEC (@String)
FETCH NEXT FROM IndexCursor INTO @Schema_TableName,@Index_Type
END
CLOSE IndexCursor
DEALLOCATE IndexCursor
END
GO
--SYNTAX
--EXEC dbo.[REBUILD_ALL_INDEXES_PROC] Index type

--TO REBUILD NONCLUSTERED COLUMNSTORE INDEXES ONLY
USE AdventureWorks2012
GO
EXEC dbo.[REBUILD_ALL_INDEXES_PROC] 6

-- TO REBUILD HEAP ONLY
USE AdventureWorks2012
GO
EXEC dbo.[REBUILD_ALL_INDEXES_PROC] 0
GO
-- TO REBUILD CLUSTERED INDEX ONLY
USE AdventureWorks2012
GO
EXEC dbo.[REBUILD_ALL_INDEXES_PROC] 1
GO
-- TO REBUILD NONCLUSTERED INDEX ONLY
USE AdventureWorks2012
GO
EXEC dbo.[REBUILD_ALL_INDEXES_PROC] 2
GO
-- TO REBUILD XML INDEX ONLY
USE AdventureWorks2012
GO
EXEC dbo.[REBUILD_ALL_INDEXES_PROC] 3
GO
-- TO REBUILD SPATIAL INDEX ONLY
USE AdventureWorks2012
GO
EXEC dbo.[REBUILD_ALL_INDEXES_PROC] 4
GO
--TO REBUILD ALL INDEXES
USE AdventureWorks2012
GO
EXEC dbo.[REBUILD_ALL_INDEXES_PROC] NULL
GO

Read Full Post »

If you would like to post any most frequent DML (Data manipulation language) transaction except Select statement in any Columnstore Index owned table, it will generate an error. (I shall post the error details in my upcoming post). You must therefore disable/ drop columnstore index before posting any DML (Data manipulation language). Given below is the script that disables all indexes with respect to category (NONCLUSTERED COLUMNSTORE, HEAP, CLUSTERED INDEX, NONCLUSTERED INDEX, XML INDEX, SPATIAL INDEX). Also, it can disable ALL indexes of any particular databases.

CREATE PROCEDURE dbo.[Disable_ALL_INDEXES_PROC]
@Type int
AS
BEGIN
DECLARE @Schema_TableName nvarchar(max)
DECLARE @String varchar(max)
DECLARE IndexCursor CURSOR FOR

Select scma.[name] + '.'
+ Quotename(tbl.name) as [Schema_TableName]
from sys.tables AS tbl
INNER JOIN sys.indexes AS i
ON (i.index_id > 0 AND i.is_hypothetical = 0)
AND (i.object_id=tbl.object_id)
INNER JOIN sys.schemas AS scma
ON tbl.schema_id=scma.schema_id
Where tbl.type='U' AND ((1=(CASE
WHEN @Type is Null THEN 1 ELSE 0 END)
OR i.type = @Type))
Order By scma.[name] + '.' + tbl.name

OPEN IndexCursor
FETCH NEXT FROM IndexCursor INTO @Schema_TableName

WHILE @@FETCH_STATUS = 0
BEGIN
SET @String = 'ALTER INDEX ALL ON ' + @Schema_TableName + ' DISABLE;'
Print @String
EXEC (@String)
FETCH NEXT FROM IndexCursor INTO @Schema_TableName
END
CLOSE IndexCursor
DEALLOCATE IndexCursor
END
GO
--SYNTAX
--EXEC dbo.[Disable_ALL_INDEXES_PROC] Index type

--TO DISABLE NONCLUSTERED COLUMNSTORE INDEXES ONLY
USE AdventureWorks2012
GO
EXEC dbo.[Disable_ALL_INDEXES_PROC] 6

-- TO DISABLE HEAP ONLY
USE AdventureWorks2012
GO
EXEC dbo.[Disable_ALL_INDEXES_PROC] 0
GO
-- TO DISABLE CLUSTERED INDEX ONLY
USE AdventureWorks2012
GO
EXEC dbo.[Disable_ALL_INDEXES_PROC] 1
GO
-- TO DISABLE NONCLUSTERED INDEX ONLY
USE AdventureWorks2012
GO
EXEC dbo.[Disable_ALL_INDEXES_PROC] 2
GO
-- TO DISABLE XML INDEX ONLY
USE AdventureWorks2012
GO
EXEC dbo.[Disable_ALL_INDEXES_PROC] 3
GO
-- TO DISABLE SPATIAL INDEX ONLY
USE AdventureWorks2012
GO
EXEC dbo.[Disable_ALL_INDEXES_PROC] 4
GO
--TO DISABLE ALL INDEXES
USE AdventureWorks2012
GO
EXEC dbo.[Disable_ALL_INDEXES_PROC] NULL
GO

Read Full Post »

Few days ago, I was working on a client database and faced some issues with ColumnStore index and to fix those issue I had to develop certain tools. Given below is the list of tools I developed :

  1. How to find all columnstore indexes with column name and datatype in a particular database ?
  2. How to disable all columnstore indexes in a particular database ?
  3. How to rebuild all columnstore indexes in a particular database ?
  4. How to drop all columnstore indexes in a particular database ?

Given below is the script of  “How to find all columnstore indexes with column name and datatype in a particular database? ”  This script not only works for columnstore indexes but also gives the list of all indexes of any particular database as well.

CREATE PROCEDURE dbo.[SEARCH_LIST_OF_ALL_INDEXES_PROC]
@Type int
AS
BEGIN
;WITH CTE AS (
SELECT TBL.object_id AS [Object ID]
, schema_name(schema_id) AS [Schema Name]
, tbl.name AS [Table Name]
, i.name AS [Index Name]
, i.type AS [Index type]
, i.type_desc AS [Index Desc]
, clmns.name AS [Column Name]
, styps.name AS [Type Name]
FROM
sys.tables AS tbl
INNER JOIN sys.indexes AS i
ON (i.index_id > 0 and i.is_hypothetical = 0)
AND (i.object_id=tbl.object_id)
INNER JOIN sys.index_columns AS ic
ON (ic.column_id > 0 and (ic.key_ordinal > 0
OR ic.partition_ordinal = 0
OR ic.is_included_column != 0))
AND (ic.index_id=CAST(i.index_id AS int)
AND ic.object_id=i.object_id)
INNER JOIN sys.columns AS clmns
ON clmns.object_id = ic.object_id
AND clmns.column_id = ic.column_id
INNER JOIN sys.systypes AS styps
ON clmns.system_type_id=styps.type
WHERE ((1=(CASE WHEN @Type is Null THEN 1 ELSE 0 END)
OR i.type = @Type)))
--To convert all datatypes into one row
SELECT [Object ID]
, [Schema Name]
, [Table Name]
, [Index Name]
, [Index Desc]
, STUFF((SELECT ', ' + [Column Name] + '(' + [Type Name] + ')'
FROM CTE AS CTE1
WHERE CTE1.[Object ID]= CTE2. [Object ID]
FOR XML PATH('')),1,1,'') as [Column Name with datatype]
FROM CTE AS CTE2
GROUP BY
[Object ID]
,[Schema Name]
,[Table Name]
,[Index Name]
,[Index Desc]
ORDER BY [Object ID],[Schema Name],[Table Name]
END
GO
-- LIST OF NONCLUSTERED COLUMNSTORE INDEX
USE AdventureWorks2012
GO
EXEC dbo.[SEARCH_LIST_OF_ALL_INDEXES_PROC] 6
GO
-- LIST OF HEAP
USE AdventureWorks2012
GO
EXEC dbo.[SEARCH_LIST_OF_ALL_INDEXES_PROC] 0
GO
-- LIST OF CLUSTERED INDEX
USE AdventureWorks2012
GO
EXEC dbo.[SEARCH_LIST_OF_ALL_INDEXES_PROC] 1
GO
-- LIST OF NONCLUSTERED INDEX
USE AdventureWorks2012
GO
EXEC dbo.[SEARCH_LIST_OF_ALL_INDEXES_PROC] 2
GO
-- LIST OF XML INDEX
USE AdventureWorks2012
GO
EXEC dbo.[SEARCH_LIST_OF_ALL_INDEXES_PROC] 3
GO
-- LIST OF SPATIAL INDEX
USE AdventureWorks2012
GO
EXEC dbo.[SEARCH_LIST_OF_ALL_INDEXES_PROC] 4
GO
-- LIST OF ALL INDEX
USE AdventureWorks2012
GO
EXEC dbo.[SEARCH_LIST_OF_ALL_INDEXES_PROC] NULL
GO

Result : List of all index
listofallindex1.2

Result : List of all NON-CLUSTERED COLUMNSTORE INDEX
listofallindex1.3

Shall post other related tools (how to disable, rebuild and drop columnstore indexes) in my upcoming posts.

Read Full Post »

Performance plays a vital role in SQL server. The importance of performance increases with the rise in the data growth. In other words, increase in data growth is directly proportional to the increase in performance. In SQL Server, index plays an important role to increase the performance as well. In SQL server 2012, we got a boost in performance (a new type of index came) namely ColumnStore Index. It is one of the nicest database features introduced in SQL Server 2012 built on xVelocity technology which is used to optimize memory. Lets discuss its syntax , purpose, examples & performance.

Syntax:
CREATE [ NONCLUSTERED ] COLUMNSTORE INDEX index_name

ON ( column [ ,…n ] )

[ WITH ( [ ,…n ] ) ]

[ ON {

{ partition_scheme_name ( column_name ) }

| filegroup_name

| “default”

}

]

[ ; ]

::=
{
[database_name. [schema_name ] . | schema_name . ]
table_name
{

::=
{
DROP_EXISTING = { ON | OFF }
| MAXDOP = max_degree_of_parallelism
}

Purpose :

The purpose of ColumnStore Index is to increase the performance in comparison to the traditional Index. It is a number of times faster than traditional index. The reason behind its performance is the way it handles the index. In Tradition Index, it stores multiple rows in each page and it retrieves in the same way. In ColumnStore Index, it stores each column in separate page and it retrieves in the same way.
In simple words you can say Tradition Index is a Row store while ColumnStore Index is a Column store.

Graphical Representation:
Given below is the graphical representation of traditional index & ColumnStore Index and you can see how each technology keeps the data pages in a different manner.

columnstoreindex1.1

Let’s test the performance of ColumnStore index Step by Step.

Step 1 :
Create a sample table.

CREATE TABLE dbo.[PurchaseOrderDetail_Sample](
[PurchaseOrderID] [int] NOT NULL,
[PurchaseOrderDetailID] [int] NOT NULL,
[DueDate] [datetime] NOT NULL,
[OrderQty] [smallint] NOT NULL,
[ProductID] [int] NOT NULL,
[UnitPrice] [money] NOT NULL,
[LineTotal] numeric(18,2),
[ReceivedQty] [decimal](8, 2) NOT NULL,
[RejectedQty] [decimal](8, 2) NOT NULL,
[StockedQty] Numeric(18,2),
[ModifiedDate] [datetime] NOT NULL)

Step 2 :
Insert some data into table (PurchaseOrderDetail_Sample), because if table has few records you cannot measure the performance of columnstore index properly.

--This insertion is just to demonstrate,
--It is not recommended on production server.
Insert into dbo.[PurchaseOrderDetail_Sample]
Select * from [Purchasing].[PurchaseOrderDetail]
GO 100

Step 3 :
Next step is to create a Columnstore index in this table.

CREATE NONCLUSTERED COLUMNSTORE INDEX
[IX_PurchaseOrderDetail_Sample_ColumnStore]
ON [PurchaseOrderDetail_Sample]
(UnitPrice, OrderQty,ReceivedQty,ProductID)
GO

Step 4 :
Now, it is time to create a query using this table and view the performance. Remember this query has a ColumnStore Index.

SET STATISTICS TIME ON
SET STATISTICS IO ON
--This query will use columnstore index and will return the result set.
SELECT ProductID as [Product ID], AVG(UnitPrice) as [Average Unit Price]
,SUM(OrderQty) as [Purchase Order Qty], AVG(ReceivedQty) as [Received Qty]
FROM [dbo].[PurchaseOrderDetail_Sample]
GROUP BY ProductID
ORDER BY ProductID

go
--This query will ignore columnstore index and will return the result set.
SELECT ProductID as [Product ID], AVG(UnitPrice) as [Average Unit Price]
,SUM(OrderQty) as [Purchase Order Qty], AVG(ReceivedQty) as [Received Qty]
FROM [dbo].[PurchaseOrderDetail_Sample]
GROUP BY ProductID
ORDER BY ProductID
OPTION (IGNORE_NONCLUSTERED_COLUMNSTORE_INDEX)

SET STATISTICS TIME OFF
SET STATISTICS IO OFF

Step 5 :
Lets compare the result of IO & Time Statistics for both, with columnstore index and without columnstore index.

Type

Logical Reads

CPU Time

Elapsed Time

ColumnStore

34

47 ms

342 ms

Without ColumnStore

8345

1482 ms

1473 ms

ColumnStore1.2

Execution Plan comparison :

ColumnStore1.3

Index Scan comparison :
ColumnStore1.4

Conclusion :
I am quite impressed to see the performance of Columnstore index. It is very handy and recommended in a place where you are either facing performance issues with the query or dealing with data warehouse. However, Columnstore index has some limitations as well which I will post in my upcoming post.

Read Full Post »