Survey
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
Tandem Computers wikipedia , lookup
Microsoft Jet Database Engine wikipedia , lookup
Entity–attribute–value model wikipedia , lookup
Clusterpoint wikipedia , lookup
Open Database Connectivity wikipedia , lookup
Extensible Storage Engine wikipedia , lookup
Database model wikipedia , lookup
Relational model wikipedia , lookup
Lifecycle of database code: Best development and deployment practices in SQL server 2000 and 2005 Omri Bahat, PhD SQL Farms, Inc. 703-946-0885 Agenda Key factors in every IT environment – People, Process, Technology Focus of this presentation – Process and technology in database server systems Development - Best practices, key concepts and guidelines QA - Automated tests for database releases Production - Best deployment practices – New solutions for MS-SQL 2000 and 2005 Development, packaging, distributed deployment and querying Tools that answer the dev, QA, and production requirements above, and follow the Dev to QA to Production release process – Solutions for small and large SQL farms alike Copyright © 2005-2006 SQL Farms, Inc. All Rights Reserved. Lifecycle of product changes and DB code Change requests are provided by the business unit – Requirements are passed to development Dev team scopes and composes the release code – Produces rollout and rollback code packages – The complete code base is passed to quality assurance (QA) QA tests the release code for functionality and standards – If the release does not meet expectations (business requirements, technical standards), the entire code base is returned to dev – Once the release meets the business requirements and all technical standards, it is then passed to production Production DB administrators (DBAs) rollout the release code – Unexpected rollout errors prompt release rollback Copyright © 2005-2006 SQL Farms, Inc. All Rights Reserved. Business continuity Business continuity is achieved through – Independent dev/QA/prod environments and resources Databases Database servers Network infrastructure, security accounts, user access Separate networks Geographically distributed production environments and failover DEV QA Copyright © 2005-2006 SQL Farms, Inc. All Rights Reserved. PROD Lifecycle of DB code releases - Development A staging area that imitates the production environment – Contains production business-schema (e.g., tables, views procedures, functions, user groups, roles) – Typically does not contain production-specific objects used by database administrators (e.g., DB maintenance objects) – Volume of data is significantly smaller than production Meta-data is the same; non-meta-data is different Accessible by developers and dev team members – Dev security policies are more loose than production – Domains, users, and active directory accounts are different Used to develop and test new features and functionality – Contains DB objects that are not yet available in production – As a consequence, dev environments are NOT CLEAN (!) and contain objects that should NOT make it to production Copyright © 2005-2006 SQL Farms, Inc. All Rights Reserved. Code releases - Project planning - Best coding practices DB Code Development - Step by step Determine which databases and servers are affected by the release – Typically determined by the project architecture Identify the data access rules to ensure proper connectivity – How do non-DB applications communicate with the database? ADO 2.x, ADO.Net, ODBC, JDBC, other drivers – If needed, how do databases communicate? Linked servers, RPC calls, OPENROWSET – Logins and users required for proper communications Domain users and groups, SQL server logins, DB users and roles Copyright © 2005-2006 SQL Farms, Inc. All Rights Reserved. DB Code Development: Step by step - cont’d Identify changes to the data definitions (DDL) – Tables, views, keys, constraints, indexes – Which objects need to be created or altered – Delete objects that are no longer in use, to keep production clean! Identify data manipulation (DML) requirements – Stored procedures, functions – Tune the table and view schema based on DML operations Revisit indexes on tables and views Apply triggers where needed – Identify how, when, and who calls each DML object e.g., SQL jobs, non-DB tier applications, and such – Tune user and group permissions based on needed DML operations Grant minimal permissions that will support the needed functionality With SQL 2K5 - T-SQL vs. CLR Copyright © 2005-2006 SQL Farms, Inc. All Rights Reserved. Best Practices for Data Definitions - Tables CREATE TABLE PhoneBook( FirstName VARCHAR(128), LastName VARCHAR(128), PhoneNumber VARCHAR(32)) Naming conventions – Make sure that table names follow a pre-determined naming convention e.g., every table name starts with ‘utb’ Keep table names short, precise, self-explanatory, and clean Avoid spaces and wildcards (e.g., ‘_’) in object names if possible To avoid ambiguities To easily search for the object in the database by name Explicitly indicate the table owner / schema – SQL 2K: Use dbo object owner wherever possible To avoid ambiguities and potential coding errors To avoid scripting bugs in MS tools (DMO, Query Analyzer) Security reasons Copyright © 2005-2006 SQL Farms, Inc. All Rights Reserved. Best Practices for Data Definitions - cont’d Explicitly indicate the target filegroup – Important when production databases use more than one filegroup – Specify the filegroup for Table data (location of data pages), e.g., ON [PRIMARY] TEXT / NTEXT / IMAGE / XML columns, e.g., TEXTIMAGE_ON [DEFAULT] – Talk to your production DB administrator! Make sure that total column length does not exceed 8060 bytes – SQL 2K gives a warning upon such table creation; error upon 8060+ insert – SQL 2005 handles 8060+ tables with variable length columns At a price of performance impact CREATE TABLE dbo.utbPhoneBook( FirstName VARCHAR(128), LastName VARCHAR(128), PhoneNumber VARCHAR(32)) ON [PRIMARY] Copyright © 2005-2006 SQL Farms, Inc. All Rights Reserved. Best Practices for Data Definitions - Columns Naming convention – Column names should be standardized, self-explanatory Every table must have a unique identifier – A column with distinct entries – A set of columns that their combined value is unique Number of columns should be kept minimal Add a fixed set of columns to every table – – – – e.g., InsertTime, UpdateTime, SQLLogin, BitArray Helps to control, synchronize, and audit data Populate these columns with an UPDATE trigger Do not use timestamp/rowversion column types Column types do not contain enough information – These columns may be omitted in performance sensitive tables Minimize overhead and performance impact Copyright © 2005-2006 SQL Farms, Inc. All Rights Reserved. Best Practices for Data Definitions - Cont’d Internationalization and localization – Unicode columns for non-English strings – NVARCHAR, NCHAR, NTEXT Collation - server, database, table – Special caution with temp table - consider database_default CREATE TABLE #MyTable ( MyCol1 NVARCHAR(16) COLLATE DATABASE_DEFAULT, MyCol2 NVARCHAR(32) SQL_Latin1_General_CP1_CI_AS) SELECT * FROM ::fn_helpcollations() EXEC sp_help <name of temp table as it appears in tempdb> Copyright © 2005-2006 SQL Farms, Inc. All Rights Reserved. Best Practices for Data Definitions - cont’d CREATE TABLE dbo.utbPhoneBook( PersonID INT IDENTITY(1,1), FirstName VARCHAR(128), LastName VARCHAR(128), PhoneNumber VARCHAR(32), BitArray INT, InsertTime DATETIME, UpdateTime DATETIME, SQLLogin NVARCHAR(128)) ON [PRIMARY] GO CREATE TRIGGER dbo.TRG_utbPhoneBook_Update ON dbo.utbPhoneBook AFTER UPDATE AS UPDATE SET FROM a UpdateTime = getdate(), SQLLogin = SUSER_SNAME() dbo.utbPhoneBook a INNER JOIN inserted i ON a.PersonID = i.PersonID GO Copyright © 2005-2006 SQL Farms, Inc. All Rights Reserved. Best Practices for Data Definitions - cont’d Make sure that table columns capture data at high granularity – Recovering details from low granularity data can be difficult – e.g., PhoneNumber: CountryCode, AreaCode, NumberBody, Extension Do not allow columns to be NULL – Avoid coding ambiguities (no need to check whether col value IS NULL) – Performance gain when inserting data to sensitive (e.g., large) tables – Standardize values that will replace NULL entries, and use defaults Empty string (i.e., '') for string column types (-1) for numeric columns getdate() or ‘1/1/1900’ for date columns Avoid using the following column types – TIMESTAMP/ROWVERSION - customize your own time tracking instead – FLOAT - has overflow and rounding errors. Use DECIMAL instead. – BIT - use an (TINY)INT column as array of bits instead. Copyright © 2005-2006 SQL Farms, Inc. All Rights Reserved. Best Practices for Data Definitions - cont’d Column defaults – Assign column default value instead of allowing NULL columns – Naming conventions Default name should be assigned by the developer Make sure that default name is not automatically assigned by SQL General tips – Avoid user-defined data types if possible – Use BIGINT, or 4 TINYINT column types to store IP addresses – Use check constraints to validate the domain of column values Tips for high volume data tables – Avoid using TEXT / NTEXT / IMAGE / XML columns Minimize overhead - Data of those columns is not stored on the data pages – Use fixed (and not variable) length columns wherever possible Reduce column size control overhead Copyright © 2005-2006 SQL Farms, Inc. All Rights Reserved. Best Practices for Data Definitions - cont’d CREATE TABLE dbo.utbPhoneBook( PersonID INT IDENTITY(1,1), FirstName VARCHAR(128) NOT NULL DEFAULT '', LastName VARCHAR(128) NOT NULL DEFAULT '', CountryCode INT NOT NULL DEFAULT 1, AreaCode INT NOT NULL DEFAULT -1, NumberBody INT NOT NULL DEFAULT -1, Extension INT NOT NULL DEFAULT -1, BitArray INT NOT NULL DEFAULT 0, InsertTime DATETIME NOT NULL DEFAULT getdate(), UpdateTime DATETIME NOT NULL DEFAULT getdate(), SQLLogin NVARCHAR(128) NOT NULL) ON [PRIMARY] GO EXEC sp_helpconstraint @objname = '[dbo].[utbPhoneBook]', @nomsg = 'nomsg' GO IMPOSSIBLE TO CONTROL (e.g., drop) DEFAULTS BASED ON THEIR NAMES! Copyright © 2005-2006 SQL Farms, Inc. All Rights Reserved. Best Practices for Data Definitions - cont’d CREATE TABLE dbo.utbPhoneBook( PersonID INT IDENTITY(1,1), FirstName VARCHAR(128) NOT NULL CONSTRAINT DF_utbPhoneBook_FirstName DEFAULT '', LastName VARCHAR(128) NOT NULL CONSTRAINT DF_utbPhoneBook_LastName DEFAULT '', CountryCode INT NOT NULL CONSTRAINT DF_utbPhoneBook_CountryCode DEFAULT 1, AreaCode INT NOT NULL CONSTRAINT DF_utbPhoneBook_AreaCode DEFAULT -1, NumberBody INT NOT NULL CONSTRAINT DF_utbPhoneBook_NumberBody DEFAULT -1, Extension INT NOT NULL CONSTRAINT DF_utbPhoneBook_Extension DEFAULT -1, BitArray INT NOT NULL CONSTRAINT DF_utbPhoneBook_BitArray DEFAULT 0, InsertTime DATETIME NOT NULL CONSTRAINT DF_utbPhoneBook_InsertTime DEFAULT getdate(), UpdateTime DATETIME NOT NULL CONSTRAINT DF_utbPhoneBook_UpdateTime DEFAULT getdate(), SQLLogin NVARCHAR(128) NOT NULL) ON [PRIMARY] GO Copyright © 2005-2006 SQL Farms, Inc. All Rights Reserved. Best Practices for Data Definitions - cont’d EXEC sp_helpconstraint @objname = '[dbo].[utbPhoneBook]', @nomsg = 'nomsg' GO Copyright © 2005-2006 SQL Farms, Inc. All Rights Reserved. Best Practices for Data Definitions - Indexes Clustered indexes CREATE TABLE dbo.utbMyTable ( Col1 INT NOT NULL PRIMARY KEY CLUSTERED, Col2 VARCHAR(10) NOT NULL, Col3 DECIMAL(18, 10)) Col1 (CI) 1 2 3 4 5 6 7 8 9 10 Col2 Col3 abc 7 bcd 2.13 cde -1.9 MyString1 -123.115 MyString1 -2 abc 1.1 bcd 2.2 cde 2.1 d 8.9 Copyright © 2005-2006 SQL Farms, Inc. All Rights Reserved. Best Practices for Data Definitions - Cont’d Non-clustered indexes Copyright © 2005-2006 SQL Farms, Inc. All Rights Reserved. Col1 (CI) 1 2 3 4 5 6 7 8 9 10 Col2 Col3 abc 7 bcd 2.13 cde -1.9 MyString1 -123.115 MyString1 -2 abc 1.1 bcd 2.2 cde 2.1 d 8.9 Best Practices for Data Definitions - Cont’d TEXT, NTEXT, IMAGE, XML columns CREATE TABLE dbo.utbMyTable ( Col1 INT NOT NULL PRIMARY KEY CLUSTERED, Col2 VARCHAR(10) NOT NULL, Col3 DECIMAL(18, 10), ColText TEXT) Copyright © 2005-2006 SQL Farms, Inc. All Rights Reserved. Best Practices for Data Definitions - cont’d Every table should have a clustered index (CI) – The CI determines the physical and logical storage of table data – The CI need not be applied on the same column(s) as the primary key (PK) – The CI should be applied on most frequently queried columns Column order matters - make sure that the CI is applied correctly Which columns to index? – High cardinality column(s) that are queried often – Remember: Indexes come at a price Num of indexes increases = Slower INSERT, DB file disk size increases Maintenance is required for each index in production Indexes should only be applied on columns with high cardinality – – – – On a single column On several columns - cardinality of the combined columns value counts Otherwise, index will not be used by the optimizer Best performance when indexes are applied on unique column(s) Copyright © 2005-2006 SQL Farms, Inc. All Rights Reserved. Best Practices for Data Definitions - cont’d Avoid indexes on long (wide) column, or columns combination – Better performance achieved with shorter index rows – If possible, avoid indexes on string columns Always specify the index properties – FILLFACTOR, PAD_INDEX, FILEGROUP – In performance sensitive application, calculate the needed FILLFACTOR Instead of accepting the server default Naming convention - Simple, self-explanatory, and informative names – Ensure that index name is assigned by the user, not by the SQL server – e.g., Clustered: Non-clustered: CI_<TableName>_<Column(s)Name(s)>_<Unique> IX_<TableName>_<Column(s)Name(s)>_<Unique> Copyright © 2005-2006 SQL Farms, Inc. All Rights Reserved. Best Practices for Data Definitions - cont’d General comments and recommendations – Read and understand how indexes are implemented in practice SQL 2K and 2005 have many differences, including: – Rebuilding indexes offline – Storing column data at the leaf level of every index – Differences between unique index and unique constraint Both implemented and stored in the DB data file as indexes Support different properties and features, see OBJECTPROPERTY Constraint can be disabled – sysindexes - what do these entries mean? indid = 0 - table does not have a CI. This entry reflects the data pages indid = 1 - this entry is reserved for the clustered index indid = 255 - reserved for all TEXT / NTEXT / IMAGE columns of the table – Getting the status of an index Use sp_helpindex and INDEXPROPERTY instead of accessing sysindexes Copyright © 2005-2006 SQL Farms, Inc. All Rights Reserved. Best Practices - Keys and Constraints Why use primary / unique keys and not only a unique indexes – Indexes used for boosting query performance – Keys used for the referential and relational integrity (RI) – Keys that are not indexes are not treated as indexes by SQL server Every table must have a unique identifier – How to determine the best primary / unique key? Ask yourself the following: If I was to map a foreign key constraint to another table to ensure referential integrity, which columns would I reference? Those column(s) should be the PK. Foreign keys (FKs) – Minimize the number of columns in each FK constraint – Use the properties of the FK carefully, especially in self referencing tables CASCADE UPDATE CASCADE DELETE NOT FOR REPLICATION Copyright © 2005-2006 SQL Farms, Inc. All Rights Reserved. Best Practices for Data Definitions - cont’d Naming conventions - simple and self-explanatory – Primary keys - PK_<TableName> – Unique constraints - UQ_<TableName>_<Column(s)Name(s)> – Foreign keys - FK_<ForeignTable>_<PrimaryTable> Checking and querying keys and constraints info – Use the SQL API and not system tables sp_helpconstraint OBJECTPROPERTY INFORMATION_SCHEMA.CHECK_CONSTRAINTS INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE INFORMATION_SCHEMA.CONSTRAINT_TABLE_USAGE INFORMATION_SCHEMA.KEY_COLUMN_USAGE INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS INFORMATION_SCHEMA.TABLE_CONSTRAINTS Copyright © 2005-2006 SQL Farms, Inc. All Rights Reserved. Best Practices for Data Definitions - cont’d CREATE CLUSTERED INDEX CI_utbPhoneBook_LastName_FirstName ON dbo.utbPhoneBook (LastName, FirstName) WITH FILLFACTOR = 80, PAD_INDEX ON [DEFAULT] GO CREATE NONCLUSTERED INDEX IX_utbPhoneBook_FirstName ON dbo.utbPhoneBook (FirstName) WITH FILLFACTOR = 80, PAD_INDEX ON [DEFAULT] GO ALTER TABLE dbo.utbPhoneBook ADD CONSTRAINT PK_utbPhoneBook PRIMARY KEY NONCLUSTERED (PersonID) WITH FILLFACTOR = 80 ON [DEFAULT], CONSTRAINT UQ_CountryCode_AreaCode_NumberBody_Extension UNIQUE (CountryCode, AreaCode, NumberBody, Extension) WITH FILLFACTOR = 80 ON [DEFAULT] GO Copyright © 2005-2006 SQL Farms, Inc. All Rights Reserved. Best Practices for Data Definitions - Views Naming conventions - simple and self-explanatory – e.g., ‘vw’ prefix to view names Avoid indexed views where possible – Requires schema binding Altering views requires more work – Well-index the underlying tables instead Partitioned views – Use carefully – Examine execution plans to verify that views are used correctly Ensure that parameter sniffing works as needed Copyright © 2005-2006 SQL Farms, Inc. All Rights Reserved. Best Practices for Data Definitions - cont’d CREATE TABLE dbo.utbPartView2005 ( TimeCol DATETIME NOT NULL CONSTRAINT CK_utbPartView2005_TimeCol CHECK (TimeCol >= '1/1/2005' and TimeCol < '1/1/2006'), Info VARCHAR(1000) NOT NULL) GO ALTER TABLE dbo.utbPartView2005 ADD CONSTRAINT PK_utbPartView2005 PRIMARY KEY CLUSTERED (TimeCol) GO CREATE TABLE dbo.utbPartView2006 ( TimeCol DATETIME NOT NULL CONSTRAINT CK_utbPartView2006_TimeCol CHECK (TimeCol >= '1/1/2006' and TimeCol < '1/1/2007'), Info VARCHAR(1000) NOT NULL) GO ALTER TABLE dbo.utbPartView2006 ADD CONSTRAINT PK_utbPartView2006 PRIMARY KEY CLUSTERED (TimeCol) GO CREATE VIEW dbo.vwPartView AS SELECT * FROM dbo.utbPartView2005 UNION ALL SELECT * FROM dbo.utbPartView2006 GO Copyright © 2005-2006 SQL Farms, Inc. All Rights Reserved. Best Practices for Data Definitions - cont’d SELECT * FROM dbo.vwPartView WHERE TimeCol = '3/5/2005' DECLARE @Time DATETIME SET @Time = '3/5/2005' SELECT * FROM dbo.vwPartView WHERE TimeCol = @Time Copyright © 2005-2006 SQL Farms, Inc. All Rights Reserved. Best SQL Coding Practices Standardize naming convention – e.g., ‘fn’ prefix for functions, ‘usp’ prefix for store procedures Self-explanatory code – Well written comments throughout the code lines – Headers - functions, procedures, views GO /*================================================================================== NAME: uspGetDuplicateIndexes DESCRIPTION: Duplicate indexes are defined as distinct indexes that contain the same set of columns, in the same order. This script detects whether there are any such user defined indexes in the database, and returns their following information: (01) The object (table or indexed view) name that has a duplicate index (02) The object type (table or indexed view) (03) The columns that participate in the duplicate index (04) Index name (05) Index description (i.e., clustered, non-clustered, ON PRIMARY, etc.) . . ==================================================================================*/ CREATE PROCEDURE uspMyProc AS . . . GO Copyright © 2005-2006 SQL Farms, Inc. All Rights Reserved. Best SQL Coding Practices - cont’d /*================================================================================== NAME: uspGetDuplicateIndexes DESCRIPTION: Duplicate indexes are defined as distinct indexes that contain the same set of columns, in the same order. This script detects whether there are any such user defined indexes in the database, and returns their following information: (01) The object (table or indexed view) name that has a duplicate index (02) The object type (table or indexed view) (03) The columns that participate in the duplicate index (04) Index name (05) Index description (i.e., clustered, non-clustered, ON PRIMARY, etc.) The variable @IncludeSystemObjects can be set by the user as follows: Set @IncludeSystemObjects = 1 to return results for both system objects and user objects. To return only user tables and indexed view column info, set @IncludeSystemObjects = 0 (which is the variable default). Note: This analysis only considers user defined indexes, and not internal SQL indexes (i.e., indexes created by the auto-statistics server configuration). USER PARAMETERS: NA RESULTSET: ObjectName (name of either table or indexed view) ObjectType (table or indexed view) IndexColumnsDelimList, IndexName, IndexDescription RESULTSET SORT: ObjectName ASC, IndexColumnsDelimList ASC USING TABLES/VIEWS: sysindexes sysindexkeys USING PROCS/FNS: NA REVISIONS: DATE DEVELOPER DESCRIPTION OF REVISION VERSION ========= =============== ================================= =========== 04/18/2005 Omri Bahat Initial release 1.00 ================================================================================== Copyright © 2005-2006 SQL Farms, Inc. All Rights Reserved. Best SQL Coding Practices - cont’d First line in every stored procedure – SET NOCOUNT ON Reduced processing overhead Crucial in applications that connect via ADO 2.X (e.g., VB 6.0) – SET NOCOUNT OFF Should be applied before returning resultsets Reapply SET NOCOUNT ON as needed Copyright © 2005-2006 SQL Farms, Inc. All Rights Reserved. Best SQL Coding Practices - Do’s and Dont’s Always specify the referenced object owner (tables, procs, fns, etc.) Retrieving TOP X records – Don’t: – Do: SET ROWCOUNT X SELECT TOP X … (X can be a calculated in 2005) Always use “new” SQL – Don’t (“old” SQL): D SELECT FROM WHERE – Do (“new” SQL): F FullName = a.LastName + ', ' + a.FirstName, b.Address dbo.utbPhoneBook a WITH (NOLOCK), dbo.utbAddresses b WITH (NOLOCK) a.PersonID = b.PersonID SELECT a.LastName + ', ' + a.FirstName AS FullName, b.Address FROM dbo.utbPhoneBook a WITH (NOLOCK) INNER JOIN dbo.utbAddresses b WITH (NOLOCK) ON a.PersonID = b.PersonID Copyright © 2005-2006 SQL Farms, Inc. All Rights Reserved. Best SQL Coding Practices - Cont’d Only use SELECT in data retrieval operations – Don’t: DECLARE @MyIntVar INT DECLARE @MyTableVar TABLE (MyCol INT) D SELECT @MyIntVar = 3 INSERT INTO @MyTableVar SELECT 4 – Do: F DECLARE @MyIntVar INT DECLARE @MyTableVar TABLE (MyCol INT) SET @MyIntVar = 3 INSERT INTO @MyTableVar(MyCol) VALUES(4) Copyright © 2005-2006 SQL Farms, Inc. All Rights Reserved. Best SQL Coding Practices - Cont’d Don’t be lazy! – Write more code to save confusion – Shortcuts affect code clarity and lead to ambiguities and errors SELECT D a.LastName + ', ' + a.FirstName AS FullName, a.FirstName FROM dbo.utbPhoneBook a WITH (NOLOCK) ORDER BY 1 F D SELECT a.LastName + ', ' + a.FirstName AS FullName, a.FirstName FROM dbo.utbPhoneBook a WITH (NOLOCK) ORDER BY a.LastName + ', ' + a.FirstName EXEC uspMyProc @Val1, @Val2, @Val3 OUTPUT F EXEC dbo.uspMyProc @Param1 = @Val1, @Param2 = @Val2, @Param3 = @Val3 OUTPUT Copyright © 2005-2006 SQL Farms, Inc. All Rights Reserved. Best SQL Coding Practices - Heads up! Rule of thumb, especially in high-volume environments Anything that can go wrong, will go wrong NEVER(!) use cursors in code – Slow performance – GLOBAL cursors will result in error if referenced by several code objects – Anything that can be done with cursors can be done with WHILE loops Fully understand and know the impact of called procedures – e.g., xp_sendmail - has memory leaks! Can crash the server! – Instead, use xp_sendsmtp Copyright © 2005-2006 SQL Farms, Inc. All Rights Reserved. Best SQL Coding Practices -cont’d Fully understand the functionality and overhead in each SQL command – e.g., Checking for NULL values DECLARE @MyIntVar INT IF @MyIntVar = NULL PRINT 'Y' ELSE PRINT 'N' N IF @MyIntVar IS NULL PRINT 'Y' ELSE PRINT 'N' Y F IF ISNULL(@MyIntVar, 1) = 1 PRINT 'Y' ELSE PRINT 'N' Y IF COALESCE(@MyIntVar, -999) = -999 PRINT 'Y' ELSE PRINT 'N' Y Copyright © 2005-2006 SQL Farms, Inc. All Rights Reserved. Best SQL Coding Practices - cont’d Dynamic SQL - EXEC vs. sp_executesql – sp_executesql - can cache and reuse execution plans – EXEC cannot – Warning: both commands can prompt procedure recompilation Table variables vs. temp tables – Table variables Not transacted Non-indexed No referential integrity – Temp tables May contain statistics, thus prompt procedure recompilation Support parallelism Support INSERT … EXEC … INSERT INTO #utbMyTable EXEC sp_helpconstraint @objname = ‘utbPhoneBook', @nomsg = 'nomsg' Copyright © 2005-2006 SQL Farms, Inc. All Rights Reserved. Best SQL Coding Practices - cont’d Do not query system tables whenever possible – Use SQL server APIs instead INFORMATION_SCHEMA objects – e.g., INFORMATION_SCHEMA.TABLES, .COLUMNS, … Service stored procedures – e.g., sp_helpjob, sp_helpconstraint, sp_helpindex… The property methods (meta-data functions) – OBJECTPROPERTY, COLUMNPROPERTY, INDEXPROPERTY, … Meta data, system functions and variables – @@PROCID, @@SERVERNAME, … NEVER(!) use non-documented stored procedures – They are not guaranteed to be supported in upcoming service packs – e.g., sp_msforeachdb, xp_sqlagent_enum_jobs Copyright © 2005-2006 SQL Farms, Inc. All Rights Reserved. Best SQL Coding Practices - Locking Use the least restrictive locking / transaction mode – NOLOCK reads wherever possible: Reduce locking and contention Reduce transactional consistency overhead SELECT * FROM dbo.utbPhoneBook WITH (NOLOCK) – Remember to SET TRANSACTION ISOLATION LEVEL Crucial when querying over linked servers Wherever possible use READ UNCOMMITTED Copyright © 2005-2006 SQL Farms, Inc. All Rights Reserved. Best SQL Coding Practices - Security Grant permissions to roles, not individuals – Map individual users to roles as needed Grant minimum permissions possible to support functionality – Special care with db_owner, db_ddladmin, db_accessadmin Never use sp_OACreate/Destroy - vulnerable code! Watch out for pwdencrypt and pwdcompare – Use of these commands hints password crackers Copyright © 2005-2006 SQL Farms, Inc. All Rights Reserved. Best SQL Coding Practices - Security Leave the use of sp_configure to DBAs – Do not use it in procedures Avoid using non-secure procedures (partial list) sp_sdidebug xp_dirtree xp_enumerrorlogs xp_findnextmsg xp_grantlogin xp_makewebtask xp_perfsample xp_revokelogin xp_servicecontrol xp_sqlinventory xp_startmail xp_execresultset xp_regdeletekey xp_regenumvalues xp_availablemedia xp_dropwebtask xp_enumqueuedtasks xp_fixeddrives xp_logevent xp_msver xp_perfstart xp_runwebtask xp_snmp_getstate xp_sqlregister xp_stopmail sp_execresultset xp_regdeletevalue xp_regread xp_cmdshell xp_dsninfo xp_enumgroups xp_getfiledetails xp_loginconfig xp_perfend xp_readerrorlog xp_schedulersignal xp_snmp_raisetrap xp_sqltrace xp_subdirs xp_printstatements xp_regenumkeys xp_regwrite Copyright © 2005-2006 SQL Farms, Inc. All Rights Reserved. xp_deletemail xp_enumdsn xp_eventlog xp_getnetname xp_logininfo xp_perfmonitor xp_readmail xp_sendmail xp_sprintf xp_sscanf xp_unc_to_drive xp_displayparamstmt xp_regaddmultistring xp_regremovemultistring Best SQL Coding Practices - Errors & logging Standardize error handling and logging policies – Make sure that errors could be captured by any caller to the proc CREATE PROC dbo.uspMyProc ... @ErrCode INT = 0 OUTPUT, @ErrMsg NVARCHAR(4000) = N'' OUTPUT AS SET NOCOUNT ON DECLARE @LogCaller NVARCHAR(128) ... SET @LogCaller = OBJECT_NAME(@@PROCID) SET @ErrMsg = N'' ... EXEC @RetErr = dbo.uspCalledProc @Param1 = @Val1, @ErrCode = @tmpErrCode OUTPUT, @ErrMsg = @tmpErrMsg OUTPUT IF @@ERROR <> 0 OR @RetErr > 0 OR @tmpErrCode > 0 BEGIN SET @ErrMsg = @ErrMsg + CHAR(10) + @tmpErrMsg IF @tmpErrCode > @RetErr SET @ErrCode = @tmpErrCode ELSE SET @ErrCode = @RetErr EXEC dbo.uspLogError @LogCaller = @LogCaller, @ErrCode = @ErrCode, @ErrMsg = @ErrMsg END IF @ErrCode > 2 RETURN @ErrCode Copyright © 2005-2006 SQL Farms, Inc. All Rights Reserved. Best SQL Coding Practices - Errors handling SQL 2005 error handling features – TRY & CATCH – New error functions CREATE PROCEDURE uspGetErrorInfo AS SELECT ERROR_NUMBER() AS ErrorNumber, ERROR_SEVERITY() AS ErrorSeverity, ERROR_STATE() AS ErrorState, ERROR_PROCEDURE() AS ErrorProcedure, ERROR_LINE() AS ErrorLine, ERROR_MESSAGE() AS ErrorMessage GO BEGIN TRY -- Generate divide-by-zero error. SELECT 1/0 END TRY BEGIN CATCH -- Execute error retrieval routine. EXECUTE dbo.uspGetErrorInfo END CATCH Copyright © 2005-2006 SQL Farms, Inc. All Rights Reserved. Preparing for code deployment: - Rollout / rollback packages - Rollout results and verification - Testing database code Best Code Deployment Practices Every release MUST have a rollout and a rollback package – Production must be restored to previous state upon an error – Write rollout scripts so that they could be run multiple times IF OBJECT_ID(‘utbMyTable', 'U') IS NOT NULL DROP TABLE dbo.utbMyTable GO CREATE TABLE dbo.utbMyTable ... Write rollout verification - to be returned to dev from QA/production SET @TableName = ‘utbMyTable' IF OBJECT_ID(@TableName, 'U') IS NOT NULL BEGIN SELECT 'Table ' + @TableName + ' created successfully on ' + db_name() AS Result PRINT('Table ' + @TableName + ' created successfully on ' + db_name()) END ELSE BEGIN SELECT 'Table ' + @TableName + ' creation error on ' + db_name() AS Result PRINT('Table ' + @TableName + ' creation error on ' + db_name()) END Copyright © 2005-2006 SQL Farms, Inc. All Rights Reserved. Best Code Deployment Practices - Heads up! Ensure that scripts are run in correct order – Make sure that all dependencies are released correctly A proc that depends on a table can be release before the table is available Not recommended under best practices - sysdepends will not be updated Do not trust the data in sysdepends system table – Not a reliable source of data IF OBJECT_ID(‘utbPhoneBook', 'U') IS NOT NULL DROP TABLE dbo.utbPhoneBook GO CREATE PROC dbo.uspMyProc AS SELECT * FROM dbo.utbPhoneBook WITH (NOLOCK) GO CREATE TABLE dbo.utbPhoneBook ... Copyright © 2005-2006 SQL Farms, Inc. All Rights Reserved. Best Code Deployment Practices - cont’d Creating new objects – CREATE statement can be used safely Altering existing objects – Do not DROP and (re)CREATE Results in loss of permissions, downtime – Use ALTER instead Minimizes downtime No loss of permissions – Altering views - Heads up! Must run this immediately after view is altered EXEC sp_recompile @objname = <ViewName> Copyright © 2005-2006 SQL Farms, Inc. All Rights Reserved. Best Code Deployment Practices - cont’d Renaming existing objects – Do not rename procedures, views, triggers - ALTER them instead syscomments stores the code of those (and other) objects syscomments is not updated to reflect the rename When object is scripted from the database - old name is used! – Renaming views, tables, columns, and other objects Find all dependencies first Do not use syscomments or sp_helptext – SELECT object_name(id) from syscomments where text like ‘%utbPhoneBook%’ – syscomments chops the code line at 8000 chars – sp_helptext chops the code line at 256 chars – Code comments not omitted Using syscomments or sp_helptext will result in false negatives and false positives Reliable dependency scripts available on http://education.sqlfarms.com Copyright © 2005-2006 SQL Farms, Inc. All Rights Reserved. Best Code Deployment Practices - cont’d Before releasing functions, procedures, and views, tables – Check execution plans of proc/function queries Especially on performance sensitive objects Tune queries as needed DO NOT force queries to use specific indexes – See the BOL for the SELECT and WHERE clause – Let the optimizer do its job – Simulate production data-volume where possible Volume, statistics, and cached plans impact the execution plan – Revisit table design (e.g., indexes) based on execution plans Volume, statistics, and cached plans impact the execution plan Make sure to pass all needed documentation and info – Schema changes, users / logins, new features Copyright © 2005-2006 SQL Farms, Inc. All Rights Reserved. Best Code Deployment Practices - Attention Pay special attention to various scenarios – DB and server names in QA / Production may not be the same as dev – Code may be release on a different number of DBs in production than in dev e.g., Production has 7 Web databases, for load balancing Dev has 1 database for simulation purposes – Production user / login names may be different Prepare and pass run-time variables that will be set by DBAs before deployment – Make sure that the release code is clean and executes smoothly Keep your DBAs happy! Copyright © 2005-2006 SQL Farms, Inc. All Rights Reserved. QA - Testing database releases Doubt everything! Document DB objects and schema, if possible Read the DB code carefully – Only then deploy release to QA Compose automatic DB tests – Check for all rules and best practices listed so far – Check functionality through automated tests – Check high data volumes and performance Consult developers and DBAs as needed Return non-satisfactory code to dev Eventually, release code to production Copyright © 2005-2006 SQL Farms, Inc. All Rights Reserved. Production - Deploying DB code by DBAs Read the DB code carefully Identify potential issues – Consult developers as needed – DBAs typically understand SQL server better than developers Clear all ambiguities and open issues Consult developers and DBAs as needed Set run-time variables as dictated by developers Deploy the code to production, and prepare for rollback Monitor the rollout and verify results. Rollback if needed. Copyright © 2005-2006 SQL Farms, Inc. All Rights Reserved. Comments and questions Remember - this is just the tip of the iceberg… Copyright © 2005-2006 SQL Farms, Inc. All Rights Reserved. Thank you SQL Farms Solutions, Inc. 128 Roberts Lane, Suite 201 Alexandria, VA 22314 www.sqlfarms.com