About Me

My photo
Mumbai, Maharastra, India
He has more than 7.6 years of experience in the software development. He has spent most of the times in web/desktop application development. He has sound knowledge in various database concepts. You can reach him at viki.keshari@gmail.com https://www.linkedin.com/in/vikrammahapatra/ https://twitter.com/VikramMahapatra http://www.facebook.com/viki.keshari

Search This Blog

Showing posts with label Table Variable and Local and Global Variable. Show all posts
Showing posts with label Table Variable and Local and Global Variable. Show all posts

Saturday, November 22, 2014

How to make use of NI with Table variable with SQL Server 2014

Non clustered index in table variable is a new feature that rolls out with SQL Server 2014, but how do we make use of it, let see with an example.

Here I am creating a table variable @IndexDemo with id as primary key and stateprovinceid as non clustered column. Lets query the table variable and see whether it is using non clustered index.

declare @IndexDemo table (
       id int identity primary key clustered (i),
       city varchar(60),
       stateprovinceid int,
       index ix_stateprovinceid nonclustered (stateprovinceid)
);

insert @IndexDemo (city,stateprovinceid)
select city, stateprovinceid
from person.address;

select city
from @IndexDemo
where stateprovinceid=1;
go

Now lets check the execution plan



Here we saw our non clustered index didn’t comes into play, instead clustered index scan takes play, very odd. Let’s dig into query to find more on it

select city
from @IndexDemo
where stateprovinceid=1;
go

So if we see our query, since our predicate is on non clustered index column i.e stateprovinceid, it should do a NI seek operation then a lookup to clustered index to get city field Values.

Lets do one thing, lets modify the query to select on stateprovinceid instead of city.


declare @IndexDemo table (
       i int identity primary key clustered (i),
       city varchar(60),
       stateprovinceid int,
       index ix_stateprovinceid nonclustered (stateprovinceid)
);

insert @IndexDemo (city,stateprovinceid)
select city, stateprovinceid
from person.address;

select stateprovinceid from @IndexDemo
where stateprovinceid=1;
go

Lets see the execution plan for the same



So here we can see from execution plan that non clustered index on sateprovinceid come into play, that means when you have key lookup for clustered index, the optimizer ignoring non clustered index seek and doing clustered index scan in case of @table variable indexing.

Summary: If you are thinking to make use of non clustered index on @table variable then don’t surround your select statement columns other then non clustered index columns.

Lets rejoice, doing codingJ


Post Reference: Vikram Aristocratic Elfin Share


Table Variable Non Clustered Index not keeping correct Statistics

With table variable, the optimizer fail to predict right number of rows returned from the query execution and fall in using wrong index selection. Lets try out with an example, first we will see the same with #temp table then will check the @table variable of SQL Server 2014.

Here we are creating a temporary table with clustered and non clustered index on it.

create table #IndexDemo  (
    id­ int identity primary key clustered,
    city varchar(60),
    stateprovinceid int,
    index ix_stateprovinceid nonclustered (stateprovinceid)
);
insert #IndexDemo (city,stateprovinceid)
select city, stateprovinceid
from person.address;
go

select city
from #IndexDemo
where stateprovinceid=1;

drop table #IndexDemo

Here in above script we have temp table with stateprovinceid field as non clustered key and id as clustered index.  Now if we see the execution plan for the query
select city
from #IndexDemo
where stateprovinceid=1;

 


Now looking at execution plan we can see it has predicted 25 rows, so to efficiently retrieve it use nonclustered index that’s fair enough. Then do the lookup to get the city column from clustered index.

Now lets implement the same using SQL Server 2014 table variable.

declare @IndexDemo table (
       i int identity primary key clustered (i),
       city varchar(60),
       stateprovinceid int,
       index ix_stateprovinceid nonclustered (stateprovinceid)
);

insert @IndexDemo (city,stateprovinceid)
select city, stateprovinceid
from person.address;

select city
from @IndexDemo
where stateprovinceid=1;
go

Now lets check the execution plan

 


Here, the estimated number of row count is showing 1 which is but obvious wrong in number, but to the count, it should use Non Clustered Index seek but oddly it uses Clustered Index scan. So to our example it fail to utilize non clustered index.

Note: Be aware before you decide to go for table variable if you thinking to make use of non clustered index feature.

Let my rhythm take me with you :)


Post Reference: Vikram Aristocratic Elfin Share

Saturday, July 5, 2014

No Statistic Update for Table Variable


Read Previous Post: Statistic for @Table Variable

In previous post we were checking about the presence of Statistic for @Table Variable, here will try to dig more on execution plan to see, whether the statistics which is used by optimizer is up-to-the-minute or stale.     

Again we are using same setup code for finding our conclusion. Here we are creating our table variable and inserting 5000 records in it.

set nocount on  

declare @tab_var table
(id int primary key clustered) 

declare @i int = 0    

begin tran
 while @i < 5000
 begin
  insert into @tab_var
  values (@i)  set @i=@i+1
 end
commit tran  

let set the Statistic Profile ON to see whether any statistic created for the same.

set statistics profile on
select * from @tab_var --option(recompile)
set statistics profile off

Rows Executes StmtText                                   EstimateRows
---- -------- --------------------------------------------- ----------
5000 1        select * from @tab_var                        1        
5000 1        |--Clustered Index Scan(OBJECT:(@tab_var))    1        

From the output we can see it uses the statistic, but the estimated Rows count(1) and Actual rows counts(5000) is varying with high percentage. This means the statistic is not updated with the insertion of   5k records.

But if it is so, lets set the strict recompile Option true to the query and see the estimated Row count.

set statistics profile on
select * from @tab_var option(recompile)
set statistics profile off
Rows Executes StmtText                                   EstimateRows
---- -------- --------------------------------------------- ----------
5000 1        select * from @tab_var                        5000        
5000 1        |--Clustered Index Scan(OBJECT:(@tab_var))    5000        

So here we can see the estimated number of rows increases to 5000, that means now the plan is up-to-the-minute plan.

So what conclusion we are getting here is Statistic are available for Table Variable but statics are nit updated with DML operation.

So one need to explicitly call Option (Recompile) to make the statistic update for Table variable. And that is the difference between Table variable and Temp Table.

The joy of release of ur code is more pleasurable than keeping it with you



Post Reference: Vikram Aristocratic Elfin Share

Statistic for Table Variable


There is always a trading open for all good thing, and when it comes to using Temp Table vs Table variable, you will witness super mall promoting their cases. Here in this post we won’t separate ourselves, will take the same plane to proof our finding.

Statistic for table variable; This is a point which creates muddy fight between table variable versus Temp table, Here in this post we will try to clear the ground on this difference.

Here we are creating a table variable with just a single column, And inserting around 5000 records in it.

set nocount on  

declare @tab_var table
(id int primary key clustered) 

declare @i int = 0    

begin tran
 while @i < 5000
 begin
  insert into @tab_var
  values (@i)  set @i=@i+1
 end
commit tran  

Now here we are setting the Statistic Profile ON to see whether any statistic created for the same.

set statistics profile on
select * from @tab_var --option(recompile)
set statistics profile off


Rows Executes StmtText                                   EstimateRows
---- -------- --------------------------------------------- ----------
5000 1        select * from @tab_var                        1        
5000 1        |--Clustered Index Scan(OBJECT:(@tab_var))    1        

So here we can see, it produces the statistic of estimated rows. But what we can see the estimated Rows count is 1 where as Actual rows count is 5000, so there is a big difference, so i can conclude this as a stale statistic for table variable.

In next post we will see the work around solution for stale statistic of table variable.

Release of Code is a paradise but release from project is a saddle to the coder! J
 

Post Reference: Vikram Aristocratic Elfin Share