Professional Documents
Culture Documents
This Sample Code is provided for the purpose of illustration only and is not
intended to be used in a production environment. THIS SAMPLE CODE AND
ANY RELATED INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF
ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
PARTICULAR PURPOSE. We grant You a nonexclusive, royalty-free right to use
and modify the Sample Code and to reproduce and distribute the object code
form of the Sample Code, provided that You agree: (i) to not use Our name,
logo, or trademarks to market Your software product in which the Sample Code
is embedded; (ii) to include a valid copyright notice on Your software product in
which the Sample Code is embedded; and (iii) to indemnify, hold harmless, and
defend Us and Our suppliers from and against any claims or lawsuits, including
attorneys’ fees, that arise or result from the use or distribution of the Sample
Code.
This posting is provided "AS IS" with no warranties, and confers no rights. Use
of included script samples are subject to the terms specified at
http://www.microsoft.com/info/cpyright.htm.
http://blogs.msdn.com/b/arvindsh 1
(c) Microsoft Corporation 2013
http://blogs.msdn.com/b/arvindsh 2
(c) Microsoft Corporation 2013
http://blogs.msdn.com/b/arvindsh 3
(c) Microsoft Corporation 2013
Note: This chart will typically flip around (at least the cost does) for applications already
in PRODUCTION. In those cases, it is probably cheapest to add hardware!
http://blogs.msdn.com/b/arvindsh 4
(c) Microsoft Corporation 2013
http://blogs.msdn.com/b/arvindsh 5
(c) Microsoft Corporation 2013
Sample Script
-- Let's try again with a LIKE, but with a partial value in the Literal. You will notice that
this query uses an index seek
SELECT *
FROM Person.Person
WHERE LastName LIKE 'Smi%'
GO
-- Next, switch to a total wildcard query observe what happens – an index scan
SELECT *
FROM Person.Person
WHERE LastName LIKE '%mi%‘
Full text indexes might be a more appropriate choice in the ‘total wildcard’ case.
http://blogs.msdn.com/b/arvindsh 6
(c) Microsoft Corporation 2013
Sample script for serial execution (you need a multi-CPU machine for this)
Use [tempdb]
GO
-- First without the UDF you can see a parallel scan is in place
select sum(S1.OrderQty + S2.OrderQty)
from AdventureWorks.sales.SalesOrderDetail S1,
http://blogs.msdn.com/b/arvindsh 7
(c) Microsoft Corporation 2013
AdventureWorks.sales.SalesOrderDetail S2
where S1.productid = 997
GO
-- Then with the UDF. Show estimated plan only. Note the absence of any parallelism in
the operators.
-- NOTE: this query is NOT functionally equivalent to the above. However, in terms of data
access the raw cost is of a similar magnitude.
select tempdb.dbo.ComputeNum(S1.OrderQty + S2.OrderQty)
from AdventureWorks.sales.SalesOrderDetail S1,
AdventureWorks.sales.SalesOrderDetail S2
where S1.productid = 997
GO
http://blogs.msdn.com/b/arvindsh 7
(c) Microsoft Corporation 2013
Status bits
Fixed length data size
Fixed length data
Total number of columns
Null bitmap
Variable length column count
Variable length column offsets
Variable length data
Varchar(2) usage is documented http://msdn.microsoft.com/en-
us/library/Dd193263(v=VS.100).aspx
http://blogs.msdn.com/b/arvindsh 8
(c) Microsoft Corporation 2013
Sample script
USE TEMPDB
GO
SET NOCOUNT ON
INSERT SmallVariableStringSizes VALUES ('a')
GO 100000
SET NOCOUNT ON
INSERT SmallFixedStringSizes VALUES ('a')
GO 100000
-- Compare row sizes, you will see the SmallVariableStringSizes is actually bigger!
select avg_record_size_in_bytes, *
from sys.dm_db_index_physical_stats(db_id(), object_id('SmallVariableStringSizes'), null,
null, 'detailed')
select avg_record_size_in_bytes, *
from sys.dm_db_index_physical_stats(db_id(), object_id('SmallFixedStringSizes'), null,
null, 'detailed')
Go
http://blogs.msdn.com/b/arvindsh 8
(c) Microsoft Corporation 2013
Sample script
USE AdventureWorks
GO
http://blogs.msdn.com/b/arvindsh 9
(c) Microsoft Corporation 2013
Sample script
http://blogs.msdn.com/b/arvindsh 10
(c) Microsoft Corporation 2013
Defense in depth:
Sample script
USE TEMPDB
GO
http://blogs.msdn.com/b/arvindsh 11
(c) Microsoft Corporation 2013
(
@LName varchar(50)
)
AS
DECLARE @SQL NVARCHAR(4000)
Print @SQL
EXECUTE (@SQL)
GO
http://blogs.msdn.com/b/arvindsh 11
(c) Microsoft Corporation 2013
Sample script
USE AdventureWorks
GO
SET STATISTICS IO ON
GO
-- First the traditional approach, on SQL 2005 AdventureWorks database this will scan
(due to lack of a supporting index)
DECLARE @rowcount int
SELECT @rowcount = COUNT(*)
FROM Person.Contact
WHERE LastName = 'Diaz'
IF (@rowcount > 0)
BEGIN
Print 'has rows'
END
GO
http://blogs.msdn.com/b/arvindsh 12
(c) Microsoft Corporation 2013
-- Next, the optimized version with EXISTS. This will also ‘scan’ but the scan stops after
the first matching row. So it turns out to be much more performant.
-- You can also validate this from the logical reads count in the messages window
IF EXISTS (SELECT *
FROM Person.Contact
WHERE LastName = 'Diaz')
BEGIN
Print 'has rows'
END
GO
http://blogs.msdn.com/b/arvindsh 12
(c) Microsoft Corporation 2013
Sample script
http://blogs.msdn.com/b/arvindsh 13
(c) Microsoft Corporation 2013
Sample script
http://blogs.msdn.com/b/arvindsh 14
(c) Microsoft Corporation 2013
-- rewrite the query in another way to use the computed column explicitly:
SELECT BusinessEntityID, TrimmedName
FROM Person.Person
WHERE TrimmedName = 'Smith'
GO
http://blogs.msdn.com/b/arvindsh 14
(c) Microsoft Corporation 2013
http://blogs.msdn.com/b/arvindsh 15
(c) Microsoft Corporation 2013
Sample script
USE TEMPDB
GO
-- Create a CL index on LastName, this will support range queries pretty well
CREATE CLUSTERED INDEX CL_PersonTemp ON PersonTemp(LastName)
GO
SELECT *
FROM PersonTemp
WHERE LastName = @LName
http://blogs.msdn.com/b/arvindsh 16
(c) Microsoft Corporation 2013
GO
SELECT *
FROM PersonTemp
WHERE LastName = @LName
GO
-- This problem is quite common with JDBC drivers which send all strings as Unicode by
default
-- reference http://sqlcat.com/sqlcat/b/msdnmirror/archive/2010/04/05/character-data-
type-conversion-when-using-sql-server-jdbc-drivers.aspx
http://blogs.msdn.com/b/arvindsh 16
(c) Microsoft Corporation 2013
http://blogs.msdn.com/b/arvindsh/archive/2011/02/15/option-recompile-redux-a-k-a-
parameter-embedding-optimization-not-working.aspx
http://blogs.msdn.com/b/arvindsh 17
(c) Microsoft Corporation 2013
http://blogs.msdn.com/b/arvindsh 18
(c) Microsoft Corporation 2013
If you are a Premier customer then you can avail the service from PFE ‘T-SQL Patterns
and Practices Review’ – contact your TAM for details (http://www.microsoft.com/en-
us/microsoftservices/premier_support.aspx)
http://blogs.msdn.com/b/arvindsh 19
(c) Microsoft Corporation 2013
Slide Commentary: Windows Store App Labs are being offered at Tech Ed for the first
time. Developers who are in the process of building an app or have already built an app,
can get exclusive time with experts to avail design, testing and technical support. The
App Lab houses some of the best in class hardware to enable app reviews and testing.
http://blogs.msdn.com/b/arvindsh 20
(c) Microsoft Corporation 2013
http://blogs.msdn.com/b/arvindsh 21
(c) Microsoft Corporation 2013
http://blogs.msdn.com/b/arvindsh 22
(c) Microsoft Corporation 2013
http://blogs.msdn.com/b/arvindsh 23
(c) Microsoft Corporation 2013
http://blogs.msdn.com/b/arvindsh 24