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

Monday, June 23, 2014

Sometime Index SCAN Operation outperform Index SEEK


Here I will try to stimulate an example where we will see Index scan outperform Index seek. But before that let me define theses two term.


Index Scan: Scan touches every row in a table, whether or not it qualifies the where predicate. It is good if your table is small or most rows qualifies where predicate.

Index Seek: Whereas Seek only touches those rows and pages which qualifies where predicate. It is efficient when you have big table and only a small set of data qualifies your predicate.

Lets come back to our problem statement, to stimulate the situation where index scan outperform we are creating a table with five column.

create table Tab_ScanVsSeek
(id int identity(1,1) primary key,
col1 varchar(300) not null default newid(),
col2 varchar(300) not null default newid(),
col3 varchar(300) not null default newid(),
col4 datetime not null default getdate())
go
Command(s) completed successfully.

Table is ready, lets insert some good amount of records in it.

set nocount on
go
insert into Tab_ScanVsSeek default values
go 100000
Beginning execution loop
Batch execution completed 100000 times.

select * from Tab_ScanVsSeek

Now here we are creating non clustered index on col1,col2,col3 leaving col4 out of index.

create nonclustered index ix_ScanVsSeek_Col1Col2Col3 on Tab_ScanVsSeek(col1, col2, col3)
go
Command(s) completed successfully.

Now lets fire the query to get the records where col1 starts with ‘a’. and see the statistic of the query.

set statistics io on
select *
from Tab_ScanVsSeek
where col1 like 'a%'
set statistics io off
Table 'Tab_ScanVsSeek'. Scan count 1, logical reads 1702, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

So we can see Logical read is 1702 and in the execution plan below we can see even though we have non cluster index on col1, the index didn’t participate in query execution.



Now lets force the query to use the NON CLUSTERED index we created on the column col1, and see the result in term of logical read.

set statistics io on
select *
from Tab_ScanVsSeek with(index = ix_ScanVsSeek_Col1Col2Col3)
where col1 like 'a%'
set statistics io off

Table 'Tab_ScanVsSeek'. Scan count 1, logical reads 19352, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

Here we saw the Logical reads increased to 19352, which s extreme big number compare to previous approach. If you see execution plan Non cluster Index comes into play, and if dig more on Execution plan, the cost increased due to Key Lookup operator. So we found in this situation Index scan perform better.



Now lets execute both the query in single batch and find which index take less cost compare to other

set statistics io on
select *
from Tab_ScanVsSeek
where col1 like 'a%'
set statistics io off

set statistics io on
select *
from Tab_ScanVsSeek with(index = ix_ScanVsSeek_Col1Col2Col3)
where col1 like 'a%'
set statistics io off


So here we saw, from batch execution of both query at a time that query1 take cost of only 18% of total batch execution whereas Index seek takes 82% high cost. So the conclusion is in this example index seek outperform index scan.

Coder cannot afford to lose temperament; this is the heart and soul of every programming! J
 

Post Reference: Vikram Aristocratic Elfin Share

Wednesday, June 18, 2014

Creating series '22-47' '23-48' '24-49' in incremental order


Today I got a question in one of the SQL Forum, the problem statement was
“Hi, I have string like '21-46' i need output like '22-47' '23-48' '24-49'incremental order. etc...plz help me..

This reminds me the Pl/SQL session we use to have in our college days and my dbms faculty, pretty Snehal Mam…

So here he is the answer for the same.

create proc sp_NoSeries
@howLong int,
@strNo varchar(50)
as
begin
 try
     declare @cntr int
     declare @no1 int
     declare @no2 int
    declare @msg varchar(100)
   
     set @howLong = 6
     set @cntr = 0

     while (@cntr<@howLong)
     begin
           print @strNo
           set @no1=cast(substring(@strNo,0,charindex('-',@strNo)) as int) + 1
           set @no2=cast(substring(@strNo,charindex('-',@strNo)+1,len(@strNo)) as int) + 1
          
           set @strNo=cast(@no1 as varchar(10)) +'-' + cast(@no2 as varchar(10))
          
           set @cntr = @cntr +1
     end
 end try
 begin catch
     print 'Error occur that is '
     set @msg = (select error_message())
     print @msg
 end catch
go

Lets execute the procedure.

exec sp_NoSeries 6,'21-46'
21-46
22-47
23-48
24-49
25-50
26-51

exec sp_NoSeries 6,'21-df46'
21-df46
Error occur that is
Conversion failed when converting the varchar value 'df46' to data type int.

To be happy always, be a coder, to learn happiness, love coder! J
 

Post Reference: Vikram Aristocratic Elfin Share

Friday, June 13, 2014

What does TimeStamp/Rowversion does?

Rowversion /Timestamp is a datatype which stores 8byte binary number. Each time any insert/update operation performed on a table having Rowversion column, the value of row version for inserted or updated rows changes to the latest counter of Rowversion.

A table can have maximum of only one column as rowversion datatype.
Timestamp is synonym to the Rowversion data type.

Lets see with an example, how we can use rowversion as a column in our table.

create table RowVersion_TB
(col1 int, col2 int, timestamp);
Command(s) completed successfully.

Now we have our table created with  rowversion datatype as one of the column. Lets insert few records in it.

insert into RowVersion_TB (col1, col2)
select 1,100 union all
select 2,200 union all
select 3,300

Lets query the table to see what values appears in the rowversion field.

select * from RowVersion_TB
col1        col2        timestamp
----------- ----------- ------------------
1           100         0x00000000000007D4
2           200         0x00000000000007D5
3           300         0x00000000000007D6

(3 row(s) affected)

Alright , the value of rowversion column is in increamented order. Lets update a row say where col1=3 and see how it affect rowversion data.

update RowVersion_TB
set col2=400
where col1=3

select * from RowVersion_TB
col1        col2        timestamp
----------- ----------- ------------------
1           100         0x00000000000007D4
2           200         0x00000000000007D5
3           400         0x00000000000007D7

(3 row(s) affected)

See the rowversion value changed when we change the data of col2 to 07D7

Lets again update the first row of the table to see, the changed value of Rowversion

update RowVersion_TB
set col2=10
where col1=1

select * from RowVersion_TB
col1        col2        timestamp
----------- ----------- ------------------
1           10          0x00000000000007D8
2           200         0x00000000000007D5
3           400         0x00000000000007D7

(3 row(s) affected)

Ah, notice that col1 1 has most updated Rowversion value. So most recently updated record has latest rowversion information.

Coder always have reason to avoid outing and shoping! J