Please start any new threads on our new site at https://forums.sqlteam.com. We've got lots of great SQL Server experts to answer whatever question you can come up with.

 All Forums
 Site Related Forums
 The Yak Corral
 An evil date

Author  Topic 

PSamsig
Constraint Violating Yak Guru

384 Posts

Posted - 2011-03-18 : 19:05:27
Sorry if this has already been debated to death, but I have been out of the loop here for a while.

Fresh home from DevWeek/SQL Server DevCon in London this past week, i had my head fille with lots of cool stuff, I hardly have had the time to process, but for one in particular.
I attended a talk about some of the cool new features in SQL Server 2008 (as I already said, I am a bit behind), one of them being the new date type. Nothing much groundbreaking about that, but for:
WHERE CONVERT(date, some_indexed_datetime_col) = '20110318'
is sargable, and even worse, it performes bettet than:
WHERE some_indexed_datetime_col >= '20110318' AND some_indexed_datetime_col < '20110319'
which means that I will start using it when opertunity arise, which again means someone will read my code and think that all kinds of non-sargable nonses is fine as well ... and the world ends in a puff of smoke and an evil laughter!

-- If you give someone a program, you will frustrate them for a day; if you teach them how to program, you will frustrate them for a lifetime.

Michael Valentine Jones
Yak DBA Kernel (pronounced Colonel)

7020 Posts

Posted - 2011-03-18 : 23:43:56
Interesting, but have you actually tested that it performs better?

I did, and what I saw was that the first query plan transformed internally into a query in the form of:
where indexed_datetime_col > @StartDate and indexed_datetime_col < @EndDate
and actually had a query plan identical to the second, except for the computation of @StartDate and @EndDate in the first query.


Also, the execution statistics were identical for both:
Table 'T_DATE'. Scan count 1, logical reads 2, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

I would say that they perform equally well, but see no reason to believe that the first performs better.



-- Test code

CREATE table T_DATE (DT datetime not null primary key clustered )

-- Load table with 109,573 dates
insert into T_DATE(DT)
select date from dbo.F_TABLE_DATE('19000101','21991231') ORDER BY date

select * from T_DATE a WHERE CONVERT(date,a.DT) = '20110318'

select * from T_DATE a WHERE a.DT >= '20110318' and a.DT < '20110319'







CODO ERGO SUM
Go to Top of Page

SwePeso
Patron Saint of Lost Yaks

30421 Posts

Posted - 2011-03-19 : 01:45:26
There is a little overhead for first query
StmtText
|--Nested Loops(Inner Join, OUTER REFERENCES:([Expr1005], [Expr1006], [Expr1004]))
|--Compute Scalar(DEFINE:(([Expr1005],[Expr1006],[Expr1004])=GetRangeThroughConvert(CONVERT_IMPLICIT(date,[@1],0),CONVERT_IMPLICIT(date,[@1],0),(62))))
| |--Constant Scan
|--Clustered Index Seek(OBJECT:([tempdb].[dbo].[T_DATE].[PK__T_DATE__3214621725C12FCC] AS [a]), SEEK:([a].[DT] > [Expr1005] AND [a].[DT] < [Expr1006]), WHERE:(CONVERT(date,[tempdb].[dbo].[T_DATE].[DT] as [a].[DT],0)=CONVERT_IMPLICIT(date,[@1],0)) ORDERED FORWARD)


And the second query
StmtText
|--Clustered Index Seek(OBJECT:([tempdb].[dbo].[T_DATE].[PK__T_DATE__3214621725C12FCC] AS [a]), SEEK:([a].[DT] >= CONVERT_IMPLICIT(datetime,[@1],0) AND [a].[DT] < CONVERT_IMPLICIT(datetime,[@2],0)) ORDERED FORWARD)

There seem to be some optimization done for the date datatype but still more work is needed.


N 56°04'39.26"
E 12°55'05.63"
Go to Top of Page

SwePeso
Patron Saint of Lost Yaks

30421 Posts

Posted - 2011-03-19 : 01:52:02
And you should know that the internal function GetRangeThroughConvert has a bug in it when using some collations.
See https://connect.microsoft.com/SQLServer/feedback/details/484426/wrong-results-with-getrangethroughconvert-and-index-seek-under-some-collations



N 56°04'39.26"
E 12°55'05.63"
Go to Top of Page

SwePeso
Patron Saint of Lost Yaks

30421 Posts

Posted - 2011-03-19 : 01:53:35
A better explanation here
http://blogs.msdn.com/b/craigfr/archive/2008/06/05/implicit-conversions.aspx



N 56°04'39.26"
E 12°55'05.63"
Go to Top of Page

PSamsig
Constraint Violating Yak Guru

384 Posts

Posted - 2011-03-23 : 15:19:59
I have been wating for the axamples from the talk to be published, and I can reproduce that date type query optimation is slightly superior to the 'old' method.

use northwind
go

-- index seek
select orderid, customerid, orderdate from orders
where orderdate >= '19970324' and OrderDate < '19970325';

-- index seek, cheaper plan than first one
select orderid, customerid, orderdate from orders
where convert(date, orderdate) = '19970324';

Gives a execute ratio of 53% for the first and 47% for the second, it is correct though, that the execution plan for the second one seems more complicated (makes a constant table on which it join through), but unless my SSMS lies, it is faster.

Apart for the oddness of being (slightly) faster, what troubles me is that it is now much more difficult to teach people about what constructs is sargable and what is not.

The session I got this from was by Bob Beauchemin, and I know that in a session I didn't have time to attend, Itzik Ben-Gan recomended this as well, in case anyone in familiar with either.

-- If you give someone a program, you will frustrate them for a day; if you teach them how to program, you will frustrate them for a lifetime.
Go to Top of Page

Michael Valentine Jones
Yak DBA Kernel (pronounced Colonel)

7020 Posts

Posted - 2011-03-23 : 16:13:06
quote:
Originally posted by PSamsig

I have been wating for the axamples from the talk to be published, and I can reproduce that date type query optimation is slightly superior to the 'old' method.

use northwind
go

-- index seek
select orderid, customerid, orderdate from orders
where orderdate >= '19970324' and OrderDate < '19970325';

-- index seek, cheaper plan than first one
select orderid, customerid, orderdate from orders
where convert(date, orderdate) = '19970324';

Gives a execute ratio of 53% for the first and 47% for the second, it is correct though, that the execution plan for the second one seems more complicated (makes a constant table on which it join through), but unless my SSMS lies, it is faster.

Apart for the oddness of being (slightly) faster, what troubles me is that it is now much more difficult to teach people about what constructs is sargable and what is not.

The session I got this from was by Bob Beauchemin, and I know that in a session I did have time to attend, Itzik Ben-Gan recomended this as well, in case anyone in familiar with either.

-- If you give someone a program, you will frustrate them for a day; if you teach them how to program, you will frustrate them for a lifetime.



Your results only have the plan, not the execution statistics for each query.
Example:
Scan count 1, logical reads 2, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.




CODO ERGO SUM
Go to Top of Page

PSamsig
Constraint Violating Yak Guru

384 Posts

Posted - 2011-03-23 : 17:12:11
Let me modify your own test exampel, just to make it slightly more realistic:
CREATE TABLE dbo.T_DATE(
ID int IDENTITY(1,1) NOT NULL,
DT datetime NOT NULL,
Filler varchar(50) NULL,
CONSTRAINT PK_T_DATE PRIMARY KEY CLUSTERED (ID)
)
GO

-- Load table with 109,573 dates
insert into T_DATE(DT)
select date from dbo.F_TABLE_DATE('19000101','21991231')
GO

CREATE NONCLUSTERED INDEX IX_T_DATE_DT ON dbo.T_DATE (DT)
GO

SET STATISTICS IO ON
GO

select * from T_DATE a WHERE a.DT >= '20110318' and a.DT < '20110319'

select * from T_DATE a WHERE CONVERT(date,a.DT) = '20110318'


the IO statistics is excatly the same
Table 'T_DATE'. Scan count 1, logical reads 4, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
but the excecution ratio is 56%/44%, not bad if you ask me.

-- If you give someone a program, you will frustrate them for a day; if you teach them how to program, you will frustrate them for a lifetime.
Go to Top of Page

Michael Valentine Jones
Yak DBA Kernel (pronounced Colonel)

7020 Posts

Posted - 2011-03-23 : 17:24:49
The execution stats are the only thing that really count.

If it reads the same number of pages with the same cpu, then it doesn't really matter about the ratio in the query plan display.

The difference in the ratio is more about SQL Server getting lost when creating the estimate.







CODO ERGO SUM
Go to Top of Page

PSamsig
Constraint Violating Yak Guru

384 Posts

Posted - 2011-03-24 : 03:53:16
To make a difference we need even more data:
-- Waste of time until we are done expanding table
DROP INDEX dbo.T_DATE.IX_T_DATE_DT
GO

-- Make our table a desent size
INSERT T_DATE (DT) SELECT DT FROM T_DATE -- 2
INSERT T_DATE (DT) SELECT DT FROM T_DATE -- 4
INSERT T_DATE (DT) SELECT DT FROM T_DATE -- 8
INSERT T_DATE (DT) SELECT DT FROM T_DATE -- 16
INSERT T_DATE (DT) SELECT DT FROM T_DATE -- 32
INSERT T_DATE (DT) SELECT DT FROM T_DATE -- 64
INSERT T_DATE (DT) SELECT DT FROM T_DATE --128
INSERT T_DATE (DT) SELECT DT FROM T_DATE --256
GO

-- Lets add some random time part
UPDATE T_DATE SET DT = DATEADD(SECOND, abs(checksum(newid())) % (24 * 60 * 60), DT)
GO

-- Building the index again
CREATE NONCLUSTERED INDEX IX_T_DATE_DT ON dbo.T_DATE (DT ASC)
GO

SET STATISTICS IO ON
GO

select * from T_DATE a WHERE a.DT >= '20110318' and a.DT < '20110319'

select * from T_DATE a WHERE CONVERT(date,a.DT) = '20110318'


and here comes the interesting part:
(256 row(s) affected)
Table 'T_DATE'. Scan count 1, logical reads 797, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

(256 row(s) affected)
Table 'T_DATE'. Scan count 1, logical reads 772, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

In case you wonder, it is the added time part that makes the difference, without it you get the same number of logical reads.

The query ratio is now 99%/1%, which is odd, but it is still to little data to makes some real time mesures.

-- If you give someone a program, you will frustrate them for a day; if you teach them how to program, you will frustrate them for a lifetime.
Go to Top of Page
   

- Advertisement -