|
|
|
SSCertifiable
       
Group: General Forum Members
Last Login: Today @ 5:44 AM
Points: 5,102,
Visits: 20,206
|
|
Comments posted to this topic are about the item T-SQL Performance 1 at: http://www.sqlservercentral.com/Questions
Edited to include the following at 8:23 AM Feb 17, 2012
HAPPY DAYS ARE HERE AGAIN
One of, or perhaps the major objective of the QOD is to teach. In many cases, there is more teaching performed in the discussion, then in the supporting reference(s) cited, as is the case with this question.
No matter how you answered the question, if you drop into this discussion to add a comment I strongly urge you to read on. The comments so far are in themselves a wonderful lesson.
And for that I thank SQL Kiwi, Hugo Kornelis and others to numerous to mention.
If everything seems to be going well, you have obviously overlooked something.
Ron
Please help us, help you -before posting a question please read Before posting a performance problem please read
|
|
|
|
|
SSChampion
        
Group: General Forum Members
Last Login: Today @ 1:02 AM
Points: 10,989,
Visits: 10,534
|
|
It is certainly very good practice to match data types, but that is not the only way to obtain a seek here (assuming the default collation is a Windows one like Latin1_General_CI_AS rather than a SQL one like SQL_Latin1_General_CP1_CI_AS):
CREATE PROC QOD_Performance_1 @Get NVARCHAR(20) AS SELECT ID,Col FROM FirstTable WITH (FORCESEEK) WHERE Col = @Get; GO EXECUTE dbo.QOD_Performance_1 @Get = N'XYZ'
 Wondering how this works, or what the Constant Scan and Compute Scalar are for? I wrote about the hard work put in by the optimizer with these sorts of data type mismatches here:
http://sqlblog.com/blogs/paul_white/archive/2012/01/18/dynamic-seeks-and-hidden-implicit-conversions.aspx
Paul White SQL Server MVP SQLblog.com @SQL_Kiwi
|
|
|
|
|
SSCrazy Eights
        
Group: General Forum Members
Last Login: Today @ 1:21 AM
Points: 9,374,
Visits: 6,471
|
|
|
|
|
|
SSCrazy
      
Group: General Forum Members
Last Login: Thursday, May 16, 2013 3:34 PM
Points: 2,170,
Visits: 3,582
|
|
Good question
Mohammed Moinudheen
|
|
|
|
|
SSCertifiable
       
Group: General Forum Members
Last Login: Today @ 4:33 AM
Points: 5,241,
Visits: 7,049
|
|
Nice, easy question - though I'm sad that as of this time, 8% of respondends got it wrong.
There is an error in the explanation, though. You can not avoid the implicit conversion. You can only change it. Making the parameter varchar(100) instead of nvarchar(20) means that now the implicit conversion from an implicit conversion from varchar to nvvarchar during the scan, to an implicit conversion from nvarchar to varchar during the procedure call. Or you can leave the parameter as is and add an explicit cast in the query. Again, not avoiding the conversion, but making it explicit.
Hugo Kornelis, SQL Server MVP Visit my SQL Server blog: http://sqlblog.com/blogs/hugo_kornelis
|
|
|
|
|
Ten Centuries
      
Group: General Forum Members
Last Login: Today @ 2:11 AM
Points: 1,390,
Visits: 772
|
|
Hi All,
Interesting question. I think i must be doing something wrong when testing this myself though.
I've created the table and index like so:
CREATE TABLE TestTable (ID INT, Col VARCHAR(100)); GO CREATE INDEX IX_Col ON TestTable (Col); GO Then created the procedure:
CREATE PROCEDURE Test_Procedure @Get NVARCHAR(20) AS SELECT ID, Col FROM TestTable WHERE Col = @Get; Then populated the table with some random data:
DECLARE @int INT; SET @int = 1;
WHILE @int <100 BEGIN
INSERT INTO TestTable (id, col) VALUES (@int, 'name' + CAST(@int AS VARCHAR(100)));
SET @int += 1;
END Now, this does result in a table scan with the CONVERT_IMPLICIT operator.
If I then change the stored proc to use VARCHAR (or VARCHAR(100)) it still results in a table scan - however the CONVERT_IMPLICIT is gone.
Is this the correct behaviour? or am I doing something silly....
Cheers, :)
There's no kill switch on awesome!
|
|
|
|
|
Ten Centuries
      
Group: General Forum Members
Last Login: Monday, April 29, 2013 10:18 PM
Points: 1,016,
Visits: 432
|
|
I have a table containg a large number
DECLARE @int INT; SET @int = 1;
WHILE @int <=1000 BEGIN
INSERT INTO TestTable (id, col) VALUES (@int, 'name' + CAST(@int AS VARCHAR(100)));
SET @int += 1;
|
|
|
|
|
SSCrazy Eights
        
Group: General Forum Members
Last Login: Today @ 1:21 AM
Points: 9,374,
Visits: 6,471
|
|
|
|
|
|
Ten Centuries
      
Group: General Forum Members
Last Login: Monday, April 29, 2013 10:18 PM
Points: 1,016,
Visits: 432
|
|
offtop
The performant alternative: Create a Tally or Numbers Table
create table dbo.Tally(i int identity(1,1)) go insert into dbo.Tally DEFAULT VALUES go 1000000
|
|
|
|
|
Ten Centuries
      
Group: General Forum Members
Last Login: Today @ 2:11 AM
Points: 1,390,
Visits: 772
|
|
Loundy (2/17/2012)
Hi All, Interesting question. I think i must be doing something wrong when testing this myself though. I've created the table and index like so: CREATE TABLE TestTable (ID INT, Col VARCHAR(100)); GO CREATE INDEX IX_Col ON TestTable (Col); GO Then created the procedure: CREATE PROCEDURE Test_Procedure @Get NVARCHAR(20) AS SELECT ID, Col FROM TestTable WHERE Col = @Get; Then populated the table with some random data: DECLARE @int INT; SET @int = 1;
WHILE @int <100 BEGIN
INSERT INTO TestTable (id, col) VALUES (@int, 'name' + CAST(@int AS VARCHAR(100)));
SET @int += 1;
END Now, this does result in a table scan with the CONVERT_IMPLICIT operator. If I then change the stored proc to use VARCHAR (or VARCHAR(100)) it still results in a table scan - however the CONVERT_IMPLICIT is gone. Is this the correct behaviour? or am I doing something silly.... Cheers, :)
Ok, it was because my table wasn't big enough :) having 10000 rows in there demonstrated the behaviour correctly :)
There's no kill switch on awesome!
|
|
|
|