dbTalk Databases Forums  

Bind Variable Dramatically Slows Query: ASCII vs Unicode mismatch

comp.databases.ms-sqlserver comp.databases.ms-sqlserver


Discuss Bind Variable Dramatically Slows Query: ASCII vs Unicode mismatch in the comp.databases.ms-sqlserver forum.



Reply
 
Thread Tools Display Modes
  #1  
Old   
bill
 
Posts: n/a

Default Bind Variable Dramatically Slows Query: ASCII vs Unicode mismatch - 06-30-2009 , 07:07 PM






I was building a table-valued function that included this in the WHERE
clause:
AND tab.SOME_COLUMN = '0148'

I wanted to drive the query with a parameter and changed the WHERE
statement to this:
AND tab.SOME_COLUMN = @SOME_VARIABLE_CD

Simply substituting the variable for the literal caused the query to
run _four times slower_.

I checked my DECLARE statement, and found this:
DECLARE @SOME_VARIABLE_CD nvarchar(4)

The database column tab.SOME_COLUMN is ASCII (varchar) not Unicode
(nvarchar).

I changed my variable declaration to ASCII data type:
DECLARE @SOME_VARIABLE_CD varchar(4)

The query zipped back to its original speed

I suspect the performance hit when comparing varchar to nvarchar
is related to implicit conversions. However, my suspicion does not
seem to be borne out by the query plan.

I have not had a chance to test with a Unicode database.
Does anyone know why the simple DECLARE change
would have a 4x impact on query speed?

Regardless, I am going to make sure that the
ASCII/UNICODE nature of my variables matches my columns.

Thanks,

Bill

Reply With Quote
  #2  
Old   
joe.no_junk@gmail.com
 
Posts: n/a

Default Re: Bind Variable Dramatically Slows Query: ASCII vs Unicode mismatch - 07-01-2009 , 10:41 AM






On Jun 30, 4:07*pm, bill <billmacle... (AT) gmail (DOT) com> wrote:
Quote:
I was building a table-valued function that included this in the WHERE
clause:
* * *AND tab.SOME_COLUMN = '0148'

I wanted to drive the query with a parameter and changed the WHERE
statement to this:
* * *AND tab.SOME_COLUMN = @SOME_VARIABLE_CD

Simply substituting the variable for the literal caused the query to
run _four times slower_.

I checked my DECLARE statement, and found this:
DECLARE @SOME_VARIABLE_CD nvarchar(4)

The database column tab.SOME_COLUMN is ASCII (varchar) not Unicode
(nvarchar).

I changed my variable declaration to ASCII data type:
* * *DECLARE @SOME_VARIABLE_CD varchar(4)

The query zipped back to its original speed

I suspect the performance hit when comparing varchar to nvarchar
is related to implicit conversions. However, my suspicion does not
seem to be borne out by the query plan.

I have not had a chance to test with a Unicode database.
Does anyone know why the simple DECLARE change
*would have a 4x impact on query speed?

Regardless, I am going to make sure that the
ASCII/UNICODE nature of my variables matches my columns.

Thanks,

Bill
Hi. It is to do with conversions. The DBMS can't be sure that
converting
will retain the same ordering, and so it won't use indexes on that
column,
so you get a table scan.
Joe Weinstein at Oracle

Reply With Quote
  #3  
Old   
Plamen Ratchev
 
Posts: n/a

Default Re: Bind Variable Dramatically Slows Query: ASCII vs Unicode mismatch - 07-01-2009 , 10:53 AM



If you check the execution plan of the query you should see the implicit conversion for the data types:

CREATE TABLE Foo (
keycol INT PRIMARY KEY,
datacol VARCHAR(30));

INSERT INTO Foo VALUES(1, 'a');
INSERT INTO Foo VALUES(2, 'b');
INSERT INTO Foo VALUES(3, 'c');

GO

SET SHOWPLAN_TEXT ON;

GO

DECLARE @search NVARCHAR(30);

SET @search = N'b';

SELECT keycol, datacol
FROM Foo
WHERE datacol = @search;

/*

StmtText
--------------------------------------------------------------------------------------
Quote:
--Clustered Index Scan(OBJECT[Testing].[dbo].[Foo].[PK__Foo__98D78B4403439144]),
WHERECONVERT_IMPLICIT(nvarchar(30),[Testing].[dbo].[Foo].[datacol],0)=[@search]))


*/

GO

SET SHOWPLAN_TEXT OFF;

GO

DROP TABLE Foo;

--
Plamen Ratchev
http://www.SQLStudio.com

Reply With Quote
  #4  
Old   
bill
 
Posts: n/a

Default Re: Bind Variable Dramatically Slows Query: ASCII vs Unicode mismatch - 07-01-2009 , 03:39 PM



Thanks to both of your for the replies.

Plamen, thanks for the code. I had expected to see something like
this when I ran the alternate plans prior to posting, but I guess I
just missed it (plan was pretty large). It.

This little test was better because it jumped off the page.


Thanks,

Bill

Reply With Quote
  #5  
Old   
bill
 
Posts: n/a

Default Re: Bind Variable Dramatically Slows Query: ASCII vs Unicode mismatch - 07-01-2009 , 03:53 PM



Here's something interesting: The engine appears to use the index,
even if it has to do an implicit conversion.

So it isn't doing a scan, but that conversion seems to be pretty
expensive.

Using Plamens 'Foo' table (see above)

I ran this:
------------------------
DECLARE @search Nvarchar(30);
SET @search = N'1';
SELECT keycol, datacol
FROM Foo
WHERE keycol = @search;

And got this (Seek, not scan, but note the implicit CONVERT):
------------------------
Quote:
--Clustered Index Seek(OBJECT[TICDW].[dbo].[Foo].
[PK__Foo__98D78B442690946A]), SEEK[TICDW].[dbo].[Foo].[keycol]
=CONVERT_IMPLICIT(int,[@search],0)) ORDERED FORWARD)

Then I chanced the variable declaration to match the INT data type o
fthe key:
----------------------------
DECLARE @search int;
SET @search = 1;
SELECT keycol, datacol
FROM Foo
WHERE keycol = @search;

Now the engine does not do the implicit CONVERT
----------------------
Quote:
--Clustered Index Seek(OBJECT[TICDW].[dbo].[Foo].
[PK__Foo__98D78B442690946A]), SEEK[TICDW].[dbo].[Foo].[keycol]=
[@search]) ORDERED FORWARD)

Reply With Quote
  #6  
Old   
Erland Sommarskog
 
Posts: n/a

Default Re: Bind Variable Dramatically Slows Query: ASCII vs Unicode mismatch - 07-01-2009 , 06:01 PM



bill (billmaclean1 (AT) gmail (DOT) com) writes:
Quote:
Here's something interesting: The engine appears to use the index,
even if it has to do an implicit conversion.

So it isn't doing a scan, but that conversion seems to be pretty
expensive.
When you have

WHERE indexedvarcharcol = @unicodevalue

there are two possible outcomes, depending on the collation of the
varchar column. If the column has a Windows collation, SQL Server will
choose an range seek. This is possible, because in a Windows collation,
the varchar repetoire is a true subset of the Unicode set, and with
the exception of binary collations, the sort order is also the same.
The cost for this range seek is typically a factor 2-3 in my experience.

But if you have an SQL collation, varchar and nvarchar are two different
worlds, and SQL Server will discard seeking the index entirely and you
will get a scan of some sort. Depending on the table size, this can lead
to increase of tenfold, hundredfold or even thousandfold.


--
Erland Sommarskog, SQL Server MVP, esquel (AT) sommarskog (DOT) se

Links for SQL Server Books Online:
SQL 2008: http://msdn.microsoft.com/en-us/sqlserver/cc514207.aspx
SQL 2005: http://msdn.microsoft.com/en-us/sqlserver/bb895970.aspx
SQL 2000: http://www.microsoft.com/sql/prodinf...ons/books.mspx

Reply With Quote
Reply




Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off



Powered by vBulletin Version 3.5.3
Copyright ©2000 - 2012, Jelsoft Enterprises Ltd.