1 / 23

T-SQL Bad Habits and Best Practices

Learn about common bad habits in T-SQL development and best practices to improve efficiency and performance. This session covers topics such as avoiding SELECT *, choosing the correct data types, using schema prefix, and more.

wconner
Download Presentation

T-SQL Bad Habits and Best Practices

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. T-SQL: Bad Habits… and Best Practices Aaron Bertrand, Senior Consultant SQL Sentry, Inc. @AaronBertrand http://sqlsentry.com/ http://sqlperformance.com/

  2. Agenda • I’m going to talk about ways you might currently be “doing it wrong.” • Don’t take offense • I learned many of these things the hard way • Most slides have links to blog posts in the notes • Many have more details, more background, more demos • I want everyone to take away at least one thing

  3. DO NOT: SELECT * / Omit column list • The problems are not: • metadata overhead • the use of the * explicitly • Real problem is needless lookups, network, I/O • Also change management: • Views do not magically update • INSERT dbo.table SELECT * FROM ^ ^ problem problem

  4. DO: Specify lengths for (n)(var)char • Do these yield the same answer? • DECLARE @x VARCHAR = 'aaron'; • SELECT • [variable] = @x, • [concat] = CONCAT(@x,'bertrand'), • [cast] = CAST('aaron' AS VARCHAR), • [convert] = CONVERT(VARCHAR, 'aaron');

  5. DO NOT: Choose the wrong data type • All kinds of violations here: • String/numeric types for date/time data • Datetimewhen date/smalldatetime will do • Time in place of an interval • MONEY/FLOAT because they sound appropriate • NVARCHAR for postal code • VARCHAR for proper names • MAX types for URL & e-mail address • TIMESTAMP because people think it involves date/time

  6. DO: Always use the schema prefix • When creating, altering, and 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 schemas

  7. DO NOT: 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, subquery, CTE etc. does not do this • TOP here dictates the rows to include, not how to order

  8. DO: Use SET NOCOUNT ON • Eliminates DONE_IN_PROC messages • Chatter can be interpreted as resultsets by app • Even in SSMS, this chatter can slow processing • Also can make finding errors and warnings tough • BUT : Test your applications! • Some older providers may rely on this info

  9. DO NOT: Abuse date / range queries • Non-sargableexpressions • YEAR(), CONVERT(), DATEADD() against columns • Date/time shorthand • GETDATE() + 1 • Spell it out! n, ns, m, mi, mm, mcs, ms, w, wk, ww, y, yyyy • BETWEEN / calculating “end” of period • Open-ended date range is safer • Non-safe, regional date formats • m/d/y & d/m/y instead of yyyymmdd or yyyy-mm-ddThh:mm:ss

  10. DO NOT: Compare to DATEDIFF • SQL Server gets DATEDIFF(DAY, 0, GETDATE()) wrong • Leads to really bad cardinality estimates • The bug was “fixed” under trace flag 4199 • Which most of you, hopefully, aren’t running everywhere • There are many ways to skin this cat, let’s use a different way

  11. DO: Use MERGE wisely • Yes, it turns multiple statements into one • But it only prevents race conditions with explicit HOLDLOCK • There are many unresolved bugs and other issues: • http://bit.ly/merge-with-caution

  12. DO NOT: Use old-style joins • Old-style outer joins (*= / =*) • Deprecated syntax • Unpredictable results • Old-style inner joins (FROM x, y) • Easy to mix up join and filter criteria • Easier to accidentally derive Cartesian product • Not deprecated, but not recommended either

  13. DO: Use sensible naming conventions • Procedures from a real customer system: dbo.GetCustomerDetails dbo.Customer_Update dbo.Create_Customer dbo.usp_updatecust • Styles vary; even your own changes over time • Convention you choose is not the point; consistency is • Just don’t use the sp_ prefix (link in notes)

  14. DO NOT: 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

  15. DO: Use efficient cursor options • Defaults are slow and heavy-handed • Global, updateable, dynamic, scrollable • My syntax is always: DECLARE c CURSOR LOCAL FAST_FORWARD FOR …

  16. DO NOT: Default to dynamic SQL • Like cursors, not always evil – can be best • Be aware of: • Potential cache bloat (turn on “optimize for ad hoc workloads”) • “Sea of red” • Concatenating different data types into a string • SQL injection

  17. DO: Use sp_executesql, not EXEC() • sp_executesql helps thwart SQL injection • Allows use of strongly-typed parameters • But not for things like table/column names • Only partial protection, but better than zero

  18. DO NOT: CASE/COALESCE in subquery • Inner SELECT is evaluated twice. This… SELECT COALESCE((SELECT …), 0) …; • …expands to this… SELECT CASE WHEN (SELECT …) > 0 THEN (SELECT …) ELSE 0 END;

  19. DO: 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, ORMs/vendors change tactics

  20. DO NOT: Abuse COUNT For filtered count, use EXISTS: IF (SELECT COUNT(*) FROM dbo.table WHERE …) > 0 IF EXISTS (SELECT 1 FROM dbo.table WHERE …) For total count, use sys.partitions: SELECT COUNT(*) FROM dbo.table; SELECT SUM(rows) FROM sys.partitions WHERE index_id IN (0,1) AND [object_id] = …

  21. DO: Stay Employed • Always use BEGIN TRANSACTION on ad hoc updates • SQL Server doesn’t have Ctrl + Z • Otherwise, keep your resume in an open transaction • Grab MladenPrajdic’s SSMS Tools Pack • Modify the “New Query” template • Use more reliable custom connection coloring • Not free for SSMS 2012, but worth every penny

  22. DO NOT: Overuse NOLOCK • The magic, pixie-dust “turbo button” …if you’re okay with 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

  23. Plenty more…Search for bad habits at sqlblog.comPlease check the slide notes for additional info and links to blog posts and articles

More Related