Download - T-SQL : Bad Habits & Best Practices
![Page 1: T-SQL : Bad Habits & Best Practices](https://reader035.vdocuments.site/reader035/viewer/2022062305/56816380550346895dd4629e/html5/thumbnails/1.jpg)
Aaron BertrandSQL Sentry
T-SQL : Bad Habits & Best Practices
![Page 2: T-SQL : Bad Habits & Best Practices](https://reader035.vdocuments.site/reader035/viewer/2022062305/56816380550346895dd4629e/html5/thumbnails/2.jpg)
Who Am I?• Senior consultant at SQL Sentry• Microsoft MVP since 1997• Blog: sqlperformance.com /
sqlblog.com• Twitter: @AaronBertrand
2
![Page 3: T-SQL : Bad Habits & Best Practices](https://reader035.vdocuments.site/reader035/viewer/2022062305/56816380550346895dd4629e/html5/thumbnails/3.jpg)
Before we start:
• Don’t take offense– I’ve learned many of these things the hard way
• I want everyone to take away at least one thing
• Most slides have links to blog posts in the notes
3
![Page 4: T-SQL : Bad Habits & Best Practices](https://reader035.vdocuments.site/reader035/viewer/2022062305/56816380550346895dd4629e/html5/thumbnails/4.jpg)
Use SELECT * / omit columns
• Metadata overhead is NOT the problem here
• Can cause needless lookups, network, I/O
• Change management:• Views do not magically update• INSERT dbo.table SELECT * FROM
• Also, don’t just create an index because the plan, DMV or Tuning Advisor tells you to… 4
![Page 5: T-SQL : Bad Habits & Best Practices](https://reader035.vdocuments.site/reader035/viewer/2022062305/56816380550346895dd4629e/html5/thumbnails/5.jpg)
• Pop Quiz : Do these yield the same answer?
DECLARE @x VARCHAR = 'xyz';
SELECT @x, CAST('xyz' AS VARCHAR), CONVERT(VARCHAR, 'xyz');
Specify length for (n)(var)char
5
![Page 6: T-SQL : Bad Habits & Best Practices](https://reader035.vdocuments.site/reader035/viewer/2022062305/56816380550346895dd4629e/html5/thumbnails/6.jpg)
Choose the wrong data type
• All kinds of violations here:• String/numeric types for date/time data• Datetime when date/smalldatetime will do• Time in place of an interval• MONEY/FLOAT because they sound
appropriate• NVARCHAR for postal code• MAX types for URL & e-mail address• VARCHAR for proper names
6
![Page 7: T-SQL : Bad Habits & Best Practices](https://reader035.vdocuments.site/reader035/viewer/2022062305/56816380550346895dd4629e/html5/thumbnails/7.jpg)
Always use the schema prefix
• When creating, altering, referencing objects– Being explicit prevents confusion or
worse• Object resolution can work harder without it• Can yield multiple cached plans for same
query
• Even if all objects belong to dbo, specify– Eventually, you or 3rd parties will use
schemas7
![Page 8: T-SQL : Bad Habits & Best Practices](https://reader035.vdocuments.site/reader035/viewer/2022062305/56816380550346895dd4629e/html5/thumbnails/8.jpg)
Abuse ORDER BY
• ORDER BY [ordinal]– OK for ad hoc, not for production– Query or underlying structure can
change
• Popular myth: table has “natural order”– Without ORDER BY, no guaranteed order– TOP + ORDER BY in a view does not do
this• TOP here is which rows to include, not how to
order8
![Page 9: T-SQL : Bad Habits & Best Practices](https://reader035.vdocuments.site/reader035/viewer/2022062305/56816380550346895dd4629e/html5/thumbnails/9.jpg)
Use SET NOCOUNT ON
• Eliminates DONE_IN_PROC messages– Chatter can interpreted as resultsets by
app code– Even in SSMS, this chatter can slow
processing
• BUT : Test your applications!– Some older providers may rely on this
info
9
![Page 10: T-SQL : Bad Habits & Best Practices](https://reader035.vdocuments.site/reader035/viewer/2022062305/56816380550346895dd4629e/html5/thumbnails/10.jpg)
Abuse date / range queries
• Avoid non-sargable expressions- YEAR(), CONVERT(), DATEADD() against columns
• Avoid date/time shorthand- GETDATE() + 1- Spell it out! n, ns, m, mi, mm, mcs, ms, w, wk,
ww, y, yyyy
• Avoid BETWEEN / calculating “end” of period- Open-ended date range is safer- Don’t “Chop off time” with a serrated edge
10
![Page 11: T-SQL : Bad Habits & Best Practices](https://reader035.vdocuments.site/reader035/viewer/2022062305/56816380550346895dd4629e/html5/thumbnails/11.jpg)
Use safe date formats
• This is not safe at all:mm/dd/yyyy
• Always use:yyyymmdd or yyyy-mm-ddThh:mm:ss.nnn
11
![Page 12: T-SQL : Bad Habits & Best Practices](https://reader035.vdocuments.site/reader035/viewer/2022062305/56816380550346895dd4629e/html5/thumbnails/12.jpg)
Use old-style joins
• Old-style inner joins (FROM x, y)• Easy to muddle join and filter criteria • Easy to accidentally derive Cartesian product• Not deprecated, but not recommended
either
• Old-style outer joins (*= / =*)• Deprecated syntax with unpredictable
results
12
![Page 13: T-SQL : Bad Habits & Best Practices](https://reader035.vdocuments.site/reader035/viewer/2022062305/56816380550346895dd4629e/html5/thumbnails/13.jpg)
Use sensible naming conventions
• Procedures from a real customer system: dbo.GetCustomerDetails dbo.Customer_Update dbo.Create_Customer dbo.sp_updatecust
• Styles vary; even your own changes over time
• Convention you choose isn’t the point; consistency is
• Just don’t use the sp_ prefix (link in notes)13
![Page 14: T-SQL : Bad Habits & Best Practices](https://reader035.vdocuments.site/reader035/viewer/2022062305/56816380550346895dd4629e/html5/thumbnails/14.jpg)
Default to cursors
• Can be difficult to think set-based• For maintenance tasks, maybe not worth it• Not always possible to go set-based
• Cursors are often “okay” but rarely optimal
• Most common exception : running totals
14
![Page 15: T-SQL : Bad Habits & Best Practices](https://reader035.vdocuments.site/reader035/viewer/2022062305/56816380550346895dd4629e/html5/thumbnails/15.jpg)
Use efficient cursor options
• Avoid heavy locking / resource usage• My syntax is always:
DECLARE c CURSOR LOCAL FAST_FORWARD FOR …
15
![Page 16: T-SQL : Bad Habits & Best Practices](https://reader035.vdocuments.site/reader035/viewer/2022062305/56816380550346895dd4629e/html5/thumbnails/16.jpg)
Default to dynamic SQL
• Like cursors, not always evil – can be best
• However, be aware of:– Potential cache bloat
• Use “optimize for ad hoc workloads” setting– “Sea of red” – maintenance is tough– SQL injection
16
![Page 17: T-SQL : Bad Habits & Best Practices](https://reader035.vdocuments.site/reader035/viewer/2022062305/56816380550346895dd4629e/html5/thumbnails/17.jpg)
Use sp_executesql vs. EXEC()
• Helps thwart SQL injection • Allows use of strongly-typed parameters • Only partial protection, but better than zero
• Promotes better plan re-use
17
![Page 18: T-SQL : Bad Habits & Best Practices](https://reader035.vdocuments.site/reader035/viewer/2022062305/56816380550346895dd4629e/html5/thumbnails/18.jpg)
Use subqueries in CASE / COALESCE
• SELECT is evaluated twice: SELECT CASE WHEN (SELECT …) > 0 THEN (SELECT …) ELSE -1 END;
SELECT COALESCE((SELECT …), -1) …;
• One case where ISNULL() is better
18
![Page 19: T-SQL : Bad Habits & Best Practices](https://reader035.vdocuments.site/reader035/viewer/2022062305/56816380550346895dd4629e/html5/thumbnails/19.jpg)
Use consistent case / formatting
• For readability, be liberal with:• BEGIN / END• Carriage returns• Indenting
• Use semi-colons to future-proof code• Case/spacing differences yield different
plans• A concern if devs write ad hoc queries
19
![Page 20: T-SQL : Bad Habits & Best Practices](https://reader035.vdocuments.site/reader035/viewer/2022062305/56816380550346895dd4629e/html5/thumbnails/20.jpg)
Abuse COUNT
• Use EXISTS instead of this common pattern: IF (SELECT COUNT(*) FROM dbo.table WHERE …) > 0
IF EXISTS (SELECT 1 FROM dbo.table WHERE …)
• And for total count, use sys.partitions rather than:
SELECT COUNT(*) FROM dbo.table;
SELECT SUM(rows) FROM sys.partitions WHERE index_id IN (0,1) AND [object_id] = …
20
![Page 21: T-SQL : Bad Habits & Best Practices](https://reader035.vdocuments.site/reader035/viewer/2022062305/56816380550346895dd4629e/html5/thumbnails/21.jpg)
Stay Employed
• Always use BEGIN TRAN on ad hoc updates– SQL Server doesn’t have Ctrl + Z
• Otherwise, keep resume in open transaction
• Grab Mladen Prajdic’s SSMS Tools Pack– Lets you modify the “New Query”
template21
![Page 22: T-SQL : Bad Habits & Best Practices](https://reader035.vdocuments.site/reader035/viewer/2022062305/56816380550346895dd4629e/html5/thumbnails/22.jpg)
Overuse NOLOCK
• The magic, pixie-dust “turbo button” …if you like inaccuracy
• There are times it is perfectly valid– Ballpark row counts
• Usually, though, better to use RCSI– Test under heavy load – can hammer tempdb– Use scope-level setting, not table hint
22
![Page 23: T-SQL : Bad Habits & Best Practices](https://reader035.vdocuments.site/reader035/viewer/2022062305/56816380550346895dd4629e/html5/thumbnails/23.jpg)
Plenty more…Search for bad habits at sqlblog.com
Please check the slide notes for additional info and links to blog posts and articles
23
![Page 24: T-SQL : Bad Habits & Best Practices](https://reader035.vdocuments.site/reader035/viewer/2022062305/56816380550346895dd4629e/html5/thumbnails/24.jpg)
Coming up…
#SQLBITS
Speaker Title RoomJennifer Stirrup Diversity in Technology (DiTBits) Theatre
Chris Testa-O'Neill Are you interested in becoming certified in SQL Server? Exhibition B
Gavin Payne Advanced Microsoft Certifications for the SQL Server Professional Suite 3
Followed by…
![Page 25: T-SQL : Bad Habits & Best Practices](https://reader035.vdocuments.site/reader035/viewer/2022062305/56816380550346895dd4629e/html5/thumbnails/25.jpg)
#SQLBITS
Coming up…