attorneys’ fees, that arise or result from the use or ... ·...
Transcript of attorneys’ fees, that arise or result from the use or ... ·...
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.
1http://blogs.msdn.com/b/arvindsh
(c) Microsoft Corporation 2013
2http://blogs.msdn.com/b/arvindsh
(c) Microsoft Corporation 2013
3http://blogs.msdn.com/b/arvindsh
(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!
4http://blogs.msdn.com/b/arvindsh
(c) Microsoft Corporation 2013
5http://blogs.msdn.com/b/arvindsh
(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 seekSELECT * FROM Person.PersonWHERE LastName LIKE 'Smi%'GO
-- Next, switch to a total wildcard query observe what happens – an index scanSELECT * FROM Person.PersonWHERE LastName LIKE '%mi%‘
Full text indexes might be a more appropriate choice in the ‘total wildcard’ case.
6http://blogs.msdn.com/b/arvindsh
(c) Microsoft Corporation 2013
Serial execution plan behavior is documented at http://msdn.microsoft.com/en-us/library/ms191007.aspx
Sample Script for SchemaBinding issue is available from http://blogs.msdn.com/b/sqlprogrammability/archive/2006/05/12/596424.aspx
Sample script for serial execution (you need a multi-CPU machine for this)
Use [tempdb]GO
CREATE FUNCTION dbo.ComputeNum(@i int)RETURNS int-- WITH SCHEMABINDINGBEGIN
RETURN @i * 2 + 50ENDGO
-- use estimated graphical plan here
-- First without the UDF you can see a parallel scan is in placeselect sum(S1.OrderQty + S2.OrderQty) from AdventureWorks.sales.SalesOrderDetail S1,
7http://blogs.msdn.com/b/arvindsh
(c) Microsoft Corporation 2013
AdventureWorks.sales.SalesOrderDetail S2where S1.productid = 997GO
-- 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 S2where S1.productid = 997GO
DROP FUNCTION dbo.ComputeNumGO
(c) Microsoft Corporation 2013
http://blogs.msdn.com/b/arvindsh 7
RSPCV = Royal Society for Prevention of Careless Variable declarationPun on RSPCA = Royal Society for Prevention of Cruelty to Animals
Row structure (reference http://blogs.msdn.com/b/sqlserverstorageengine/archive/2006/06/23/644607.aspx)
Status bitsFixed length data sizeFixed length dataTotal number of columnsNull bitmapVariable length column countVariable length column offsetsVariable length data
Varchar(2) usage is documented http://msdn.microsoft.com/en-us/library/Dd193263(v=VS.100).aspx
8http://blogs.msdn.com/b/arvindsh
(c) Microsoft Corporation 2013
Sample script
USE TEMPDBGO
CREATE TABLE SmallVariableStringSizes(
Varchar1Col varchar(1))GO
SET NOCOUNT ONINSERT SmallVariableStringSizes VALUES ('a')GO 100000
-- Next, deal with the fixed size allocation
CREATE TABLE SmallFixedStringSizes(
Char1Col char(1))GO
SET NOCOUNT ONINSERT 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
(c) Microsoft Corporation 2013
http://blogs.msdn.com/b/arvindsh 8
Sample script
USE AdventureWorksGO
DECLARE @Name NVARCHAR (50)
SELECT @Name = NameFROM Production.Product PWHERE P.ProductModelID = 14
-- we think we have an unique value, but did we really check?-- NOTE: the IIF syntax will only work on SQL 2012 and aboveSELECT IIF(@@ROWCOUNT > 1, 'Warning; Multiple values', 'OK')
9http://blogs.msdn.com/b/arvindsh
(c) Microsoft Corporation 2013
Sample script
-- Though the syntax below will be accepted by SQL, it offers no guaranteesCREATE VIEW TestOrderByASSELECT TOP 100 PERCENT BusinessEntityID, Title, FirstName, LastNameFROM Person.PersonORDER BY LastNameGO
-- The above 'appears' to work, but does it -- really guarantee order? Let's see:SELECT * FROM TestOrderByGO
-- Let's try again with an explicit ORDER BY, -- note the SORT operator nowSELECT * FROM TestOrderByORDER BY LastName
10http://blogs.msdn.com/b/arvindsh
(c) Microsoft Corporation 2013
Only the paranoid survive: book by Andy Grove http://en.wikipedia.org/wiki/Andrew_Grove
Defense in depth:
• Platform level screening (URLScan)• App level screening (regex based checks)• Strong passwords• Use Windows authentication• Minimum privilege (no usage of SYSADMIN or DB_OWNER role members.)• Strong audit mechanism
Sample script
USE TEMPDBGO
CREATE TABLE ToBeDropped(
i int)GO
CREATE PROCEDURE InquiryProc
11http://blogs.msdn.com/b/arvindsh
(c) Microsoft Corporation 2013
(@LName varchar(50)
)AS
DECLARE @SQL NVARCHAR(4000)
-- Use the parameter as-is; results will be seen later :-)SET @SQL = CONCAT('SELECT * FROM AdventureWorks.Person.Person
WHERE LastName = ''', @LName, '''')
Print @SQL
EXECUTE (@SQL)GO
EXEC InquiryProc 'Singh' -- should get back 2 rows
-- check for the 'important' table, it is still there.select * from ToBeDropped
-- next try to 'inject' bad SQLEXEC InquiryProc 'Singh''; DROP TABLE ToBeDropped; SELECT '''
-- check for the 'important' table, it is gone!select * from ToBeDropped
-- so how does one mitigate this stuff?-- DEFENSE in DEPTH is the key-- firstly, apply URLScan at the web server to -- stop 'malformed' HTTP requests-- secondly, use app code to screen for keywords -- thirdly in the SQL layer use a CLR UDF to screen -- for such keywords in input parameter-- reference link: http://blogs.msdn.com/b/mike/archive/2008/10/15/how-to-configure-urlscan-3-0-to-mitigate-sql-injection-attacks.aspx
(c) Microsoft Corporation 2013
http://blogs.msdn.com/b/arvindsh 11
Row goals are explained at http://blogs.msdn.com/b/queryoptteam/archive/2006/03/30/564912.aspx
Sample script
USE AdventureWorksGO
SET STATISTICS IO ONGO
-- First the traditional approach, on SQL 2005 AdventureWorks database this will scan (due to lack of a supporting index) DECLARE @rowcount intSELECT @rowcount = COUNT(*) FROM Person.ContactWHERE LastName = 'Diaz'
IF (@rowcount > 0)BEGIN
Print 'has rows'ENDGO
12http://blogs.msdn.com/b/arvindsh
(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 windowIF EXISTS (SELECT *
FROM Person.ContactWHERE LastName = 'Diaz')
BEGINPrint 'has rows'
ENDGO
(c) Microsoft Corporation 2013
http://blogs.msdn.com/b/arvindsh 12
WYSIWYG = What you see is what you get
Sample script
-- Does this ORDER BY really guarantee anything?-- Note that in SQL 2008 and below, this would -- actually insert a sort operator without any logical benefit-- repeat this step twice, first in SQL 2008 and then in 2012-- SQL 2012 seems to 'optimize out' the Sort operator:Connect .\sql2008
SELECT Title, FirstName, LastNameINTO #PTempFROM AdventureWorks.Person.PersonORDER BY FirstNameGO
SELECT * FROM #PTempGO
13http://blogs.msdn.com/b/arvindsh
(c) Microsoft Corporation 2013
Sample script
-- BUT the minute you apply a function like RTRIM or LTRIM:SELECT BusinessEntityID, LastNameFROM Person.PersonWHERE LTRIM(LastName) = 'Smith'GO
-- for a moment, compare the row estimate between -- the LTRIM above and the RTRIM belowSELECT FirstName, LastNameFROM Person.PersonWHERE RTRIM(LastName) = 'Smith'GO
-- Try adding a computed column and persist it-- we are using LTRIM for this case because we saw more skewed C.E. in that caseALTER TABLE Person.PersonADD TrimmedName as LTRIM(LastName)GO
CREATE NONCLUSTERED INDEX IDX_TrimLNameON Person.Person (TrimmedName)GO
14http://blogs.msdn.com/b/arvindsh
(c) Microsoft Corporation 2013
-- Compare with these now-- compare with something with smaller C.E.-- seeks even if we have to lookup-- this is due to the 'tipping point' effectSELECT BusinessEntityID, LastNameFROM Person.PersonWHERE LTRIM(LastName) = 'Singh'GO
-- rewrite the query in another way to use the computed column explicitly:SELECT BusinessEntityID, TrimmedNameFROM Person.PersonWHERE TrimmedName = 'Smith'GO
(c) Microsoft Corporation 2013
http://blogs.msdn.com/b/arvindsh 14
15http://blogs.msdn.com/b/arvindsh
(c) Microsoft Corporation 2013
Sample script
USE TEMPDBGO
-- Create a copy of the Person table in TEMPDBSELECT BusinessEntityID, Title, FirstName, MiddleName, CAST (LastName AS VARCHAR(50)) LastNameINTO PersonTempFROM AdventureWorks.Person.PersonGO
-- Create a CL index on LastName, this will support range queries pretty wellCREATE CLUSTERED INDEX CL_PersonTemp ON PersonTemp(LastName)GO
-- Turn on actual graphical execution plan from SSMS
-- Now simulate a 'good client' queryDECLARE @LName VARCHAR(50) = 'Smith'
SELECT * FROM PersonTempWHERE LastName = @LName
16http://blogs.msdn.com/b/arvindsh
(c) Microsoft Corporation 2013
GO
-- Compare it with a 'bad client' queryDECLARE @LName NVARCHAR(50) = N'Smith'
SELECT * FROM PersonTempWHERE LastName = @LNameGO
-- 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
(c) Microsoft Corporation 2013
http://blogs.msdn.com/b/arvindsh 16
http://blogs.msdn.com/b/arvindsh/archive/2011/02/15/option-recompile-redux-a-k-a-parameter-embedding-optimization-not-working.aspx
17http://blogs.msdn.com/b/arvindsh
(c) Microsoft Corporation 2013
Isolation level note: http://connect.microsoft.com/SQLServer/feedback/details/243527/sp-reset-connection-doesnt-reset-isolation-level
18http://blogs.msdn.com/b/arvindsh
(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)
You can also contact me via. my blog: http://blogs.msdn.com/b/arvindsh
19http://blogs.msdn.com/b/arvindsh
(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.
20http://blogs.msdn.com/b/arvindsh
(c) Microsoft Corporation 2013
21http://blogs.msdn.com/b/arvindsh
(c) Microsoft Corporation 2013
22http://blogs.msdn.com/b/arvindsh
(c) Microsoft Corporation 2013
23http://blogs.msdn.com/b/arvindsh
(c) Microsoft Corporation 2013
24http://blogs.msdn.com/b/arvindsh
(c) Microsoft Corporation 2013