
|
- Try to use derived tables over temporary tables to gain better performance. A derived table is the result of using another SELECT statement in the FROM clause of a SELECT statement. i.e. SELECT MIN(Salary) FROM (SELECT TOP 5 Salary FROM Employees ORDER BY Salary Desc)
- If real-time replication is not required then don't use continuous replication. Schedule replication to occur at regular intervals to reduce server overhead.
- If you are not replicating to Microsoft Jet 4.0 databases then turn this feature off to use the faster BCP native format for the Snapshot Agent.
- Avoid replicating TEXT, NTEXT or IMAGE columns to reduce overhead.
- In SELECT statements only return fields you require and don't use 'SELECT * FROM table'. In addition it prevents the use of covered indexes impacting query performance.
- Triggers use two special tables called inserted and deleted. The inserted table contains the data of the insert prior to being committed to the database. Likewise the deleted table contains data before is it deleted from the database. Both tables are used when an update statement is issued. The inserted table contains the new data and the deleted table contains the data being updated.
- Use the T-SQL Debugger Visual Basic Add-In to debug Stored Procedures. From Visual Basic's Add-Ins Menu select T-SQL Debugger.
- There are two kinds of error in SQL Server, fatal and non-fatal. Fatal errors cause a stored procedure to abort processing and terminate the connection. Non fatal errors continue on the line of code that follows the one that caused the error.
- The @@ERROR system function contains the error ID of the last SQL statement executed. It has a value of 0 when the statement is successful. You need to check its value immediately after the statement to be checked as it's value is reset on the next statement.
- Use the RAISERROR statement to produce ad-hoc error messages.
- Use the following script to detail foreign key constraints on the specified table.
|
SELECT object_name(constid) AS constraint_name,
object_name(fkeyod) AS table_name,
col_name(fkeyid, fkey) AS column_name,
object_name(rkeyid) AS referenced_table_name,
col_name(rkeyid, rkey) AS referenced_column_name,
FROM sysforeignkeys
WHERE object_name(fkeyid) = 'Table Name Goes Here'
ORDER BY constraint_name, table_name, referenced_table_name, keyno
|
- Use the following script to detail the name of the constraints defined on the specified table.
|
SELECT constraint_name,
column_name,
ordinal_position,
FROM information_scheme.key_column_usage
WHERE constraint_catalog=db_name()
AND table_name = 'Table Name Goes Here'
ORDER BY constraint_name, ordinal_position
|
- When choosing a primary key for a table, don't select a field that can be null, stick to a single column if possible, choose a column with no embedded spaces or special characters or differential capitalisation, either integer or fixed length character data types as SQL server has to decompress variable length character data before processing, choose a field that never changes.
- An orphaned session is a session that remains open on the server then the client application has been disconnected. Execute the sp-lock procedure to find locks and the spid. A spid value of -2 indicates a connectionless or orphaned transaction. To find the process locking the records select records from the sysprocesses for the spid in question. Use the KILL command to kill the process.
- To stop queries returning the number of rows affected use SET NOCOUNT ON. This adds a significant performance improvement. Turning this option on eliminates the sending of DONE_IN_PROC messages to the client for each statement in a stored procedure.
- Standardise on a coding and naming convention, be consistent and stick to it.
- As with all programming use lots of comments to aid readability.
- Don't use wildcard characters such as '%' at the beginning of the search string as it results in a full table scan.
- Also avoid using not equals operators such as <> and NOT as they result in table and index scans.
- Don't prefix your stored procedures with 'sp_' as SQL looks in the Master database first. An 'sp_' procedure is reserved for system stored procedures.
- Use the CHAR data type when the field can't be set to NULL. If it is set to NULL it still takes the same space. So for example a variable CHAR(100) will still be 100 bytes when Null.
- Always name your columns in am INSERT statement to avoid problems when adding or dropping a column.
- Add a @Debug parameter to stored procedures. This can be a BIT data type. When passing a value of 1, print all the intermediate results, variable values using SELECT or PRINT statements, and print nothing when 0 is passed. This helps debug stored procedures.
- Use the Xp_sendmail utility to send e-mail messages directly from SQL Server. It's syntax is Xp_sendmail 'name@company.com', 'message'.
- When creating an index with a composite key ensure that the most selective columns are leftmost in the key. (A composite key is one composed of more than one column).
- Don't use the DISTINCT clause on all your queries as it impacts performance.
- Avoid using 'IS NULL', 'OR', '<>', '!=', '!>', '<', 'NOT', 'NOT EXISTS', 'NOT IN', 'NOT LIKE', 'LIKE %10' as the optimizer will not use an index to perform the search.
- When upgrading from MSDE to SQL Server clear the SQL Data Root and SQL Data Path registry entries as they can conflict with the SQL Installation.
- When rebuilding clustered index on a table that has non-clustered indexes, use the DROP_EXISTING option with the CREATE INDEX command. The DROP_EXISTING option ensures that none of the non-clustered indexes are rebuilt twice.
- On lookup tables that change little use the index option 'SP_INDEXOPTION' to lock the table rather than individual rows. The following two commands turn off both row and page locking allowing only table locking.
|
SP_INDEXOPTION 'tablename','AllowRowLocks',FALSE
P_INDEXOPTION 'tablename','AllowPageLocks',FALSE
|
- If all your subscribers in replication are SQL server then don't select the option to allow a subscriber to be Microsoft Jet 4.0. This ensures that replication uses BCP native format rather than BCP character format which is quicker.
- SQL Performance monitor includes a Performance Monitor Object called the USer Settable Object, which is a set of ten performance monitor counters that you can customise for your own purpose.
- Use SQL's Profiler tool to capture all events between your application and SQL. You can identify performance problems due to application design and watch how long events take.
- Ensure that you have a clustered index on tables that have many INSERTS even though the table may not really need one. An insert on a table without a clustered index adds the new record at the end of the table causing contention when there are many inserts.
- If the DBCC CHECKDB is taking too long use the NOINDEX option to not check non-clustered indexes. The same is true for the Check Database Integrity option when the 'Exclude indexes' option can be selected.
- Use the SQL Profiler to find out if SQL Server is running efficiently as it can.
- An update trigger runs whenever it's related table is updated. You can use the COLUMNS_UPDATED() function to check which columns have been updated and only execute the trigger on selected column changes.
- To list any traces at the client level run the DBCC TRACESTATUS(-1) command in the Query Analyser.
- Don't add identity columns to your tables to provide a primary key when an existing column in the table is unique.
- When accessing linked servers via Enterprise Manager over a slow network amend the Login time-out value. This can be found on the Tools-Options Connection Tab.
- If linked servers have the same character set and sort order as the local server set the SP_SERVEROPTION 'collation compatible' to true to reduce overhead and boost performance.
- Run queries in the Query Analyser and look at the query plan when running a remote query against a linked server to find out which parts of the query are performing on the remote server and which parts are performing on the local server.
- Capture Profiler results to a text file as using a SQL server table could impact performance of the server you are profiling.
- When a transaction affects many tables and some of the tables are heavily accessed then try to move these tables towards the end of the transaction to reduce the duration of table locks during the transaction.
- Use the Profiler option SP_Recompile event to trace when stored procedures are being recompiled. If a stored procedure is being recompiled often investigate and correct the problem.
- Use the command line tool SQLDIAG.exe to collect loads of information about SQL server and writes it to a text file in the \mssql\log folder. Details captured include error log text, system stored procedure outputs, registry information and the last 100 queries if you have the query history trace running.
- The Index Tuning wizard creates indexes in the sysindexes table with names starting with "hind_%". If the wizard is interrupted before completing these indexes and associated tables can be left undeleted. You can either delete these manually or run the script found at http://support.microsoft.com/support/kb/articles/q293/1/77.asp.
- Amend the verbose setting of the log reader agent, merge agent and snapshot agent to reduce the amount of data these processes log. These settings are amended by using the agents utility programs located in the \mssql\binn directory.
- If you need replication agents to run frequently, say every minute or so then set them to run continuously. This reduces the overhead of starting and stopping the every minute.
- For frequently run queries that use the WHERE, ORDER BY, GROUP BY, TOP or DISTINCT consider adding indexes on all columns accessed, reducing the possibility of a table scan.
- Use the 'SELECT @@Version' query to check the version of SQL Server currently running. This will return the version number and using the details below you can determine which service pack you are using.
|
2000.8.00.532 SQL Server 2000 SP2
2000.8.00.384 SQL Server 2000 SP1
2000.8.00.194 SQL Server 2000 "gold" release, no SP
7.00.1063 SQL Server 7.0 SP4
7.00.961 SQL Server 7.0 SP3
7.00.842 SQL Server 7.0 SP2
7.00.835 SQL Server 7.0 SP2 Beta
7.00.699 SQL Server 7.0 SP1
7.00.689 SQL Server 7.0 SP1 Beta
7.00.677 MSDE in Office 2000, Office Developer
7.00.623 SQL Server 7.0 "gold" release, no SP
6.50.479 SQL Server 6.5 with post SP5a update
6.50.416 SQL Server 6.5 SP5a
6.50.415 SQL Server 6.5 SP5 (Do not use as bad SP)
6.50.339 SQL Server 6.5 "Y2K" Hot-fix
6.50.297 SQL Server 6.5 included in Site Server 3
6.50.281 SQL Server 6.5 SP4
6.50.259 SQL Server 6.5 on SBS only
6.50.258 SQL Server 6.5 SP3
6.50.252 SQL Server 6.5 SP3 (Do not use as bad SP)
6.50.240 SQL Server 6.5 SP2
6.50.213 SQL Server 6.5 SP1
6.50.201 SQL Server 6.5 "gold" release
|
- Don't use the shrink database option in your maintenance plan. This is because SQL Server will have to use more resources when creating more space.
- To help you identify any replication performance issues track the following Performance Monitor counters :
|
Dist : Delivered Cmds/sec : Tracks the number of commands per second sent to subscribers from the distributor
Dist : Delivered Trans/sec : Tracks the number of transactions per second sent to subscribers from the distributor
Dist : Delivery Latency : The average amount of time it takes for a transaction to be moved from the distributor to a subscriber
|
- To clear out SQL Servers data cache (buffer) and stored procedure cache run the DBCC DROPCLEANBUFFERS and DBCC FREEPROCCACHE commands. To clear out the procedure cache for a single database run the DBCC FLUSHPROCINDB command.
- The system table syscachedobjects lists details of cached execution plans. The cachedobjtype shows the type of object in the cache, for stored procedures look for Compiled Plan and Executable Plan. The objtype column shows the type of object which is Proc for stored procedures.
- When viewing Query Execution Plans the thicker the arrow that connects icons then the greater the relative cost of that operation. Therefore pay special attention to these thick arrows to improve performance.
- The Red icon text in the Query Execution plan means that the related table is missing statistics to help the Query Optimiser come up with a better execution plan.
- When executing a stored procedure include the owner in front of the stored procedure to increase performance. i.e. EXEC dbo.usp_GetClients.
- Remove indexes that are never used by the Query Optimiser as they slow data modifications and waste space. Use the Index Wizard to help identify indexes that are not being used.
- Non-clustered indexes are best for queries that return few rows and where the index has a good selectivity (above 95%). Clustered indexes perform better for a large range of queries.
- Consider using the Transact-SQL ALTER command to modify table schemas for very large tables. Using Enterprise Manager sometimes recreates a new table based on your new schema and them moves the data from the old table into the new table.
- For investigating SQL Server installation errors check the following files :
|
sqlstp.log located in the \Windows or \WINNT directory
errorlog file located in the \MSSQL\Log directory
cnfgsvr.out file located in the \MSSQL\install directory
|
- Performing the WHERE clause on a column causes the index on that column not to be used. Rewrite the WHERE clause so that the column and function are separate, for example :
|
Function acts directly on column, and index cannot be used
|
SELECT member_number, first_name, last_name
FROM members
WHERE DATEDIFF(yy, dateofbirth, GETDATE())>21
|
Function has been separated from column and an index can be used
|
SELECT member_number, first_name, last_name
FROM members
WHERE dateofbirth < DATEADD(yy, -21, GETDATE())
|
- To determine which user thread has to wait for over a second run the following query :
|
SELECT spid, waittime, lastwaittime
FROM master..sysprocesses
WHERE waittime > 1000
|
- Use the SET STATISTICS IO ON to force SQL to report actual I/O activity on executed transactions. Disable the option with SET STATISTICS IO OFF.
- Use the SET STATISTICS TIME ON to show the actual elapsed time and CPU utilisation for every following query. Executing SET STATISTICS TIME OFF suppresses the option.
- Use the DBCC SHOW_STATISTICS command to show how effective the specified index of a particular table is.
- Use DBCC SQLPERF LOGSPACE command to show the percentage of transaction log space used.
- Avoid Inserting, Updating or Deleting large numbers of records in a single transaction as all the records affected by your action will be locked until the transaction is done.
- Use a Profiler trace to capture and view the traffic being sent from a client application to SQL Server. A Profiler trace can easily identify this type of traffic assisting in investigating performance problems.
- Use the Process Info window in Enterprise manager to identify which SPID is causing blocking locks. Right click on the SPID and choose Properties to display the offending query. You can also enter DBCC INPUTBUFFER (spid) into SQL Query Analyses to reveal the query causing the block.
|
| To transfer a diagram to a different server or database. follow the following steps after you have created a duplicate database :- |
- Check that you can make modifications to system tables by checking the properties of the server and check 'Allow modifications to system catalogs'.
- Change the type of the system table 'dtproperties' to user to trick SQL into allowing the IDENTITY_INSERT flag to be set to ON, by running the query 'UPDATE sysobjects SET xtype='U' WHERE name='dtpropertes''.
- Set the IDENTITY_INSERT property of the 'dtproperties' table to true to override the ID field by running the query 'SET IDENTITY_INSERT dtproperties ON'.
- Decide which diagrams you want to transfer by listing the fields of the dtproperties table - 'SELECT id, objectid, property, value, lvalue, version FROM database.dbo.dtproperties'. To determine which table to transfer look for 'DtgSchemaName' value in the property column. These rows will have a value in the value column which is the diagram name. Note the objectid for the row.
- All the records for this diagram have the same objectid, so you need to transfer all the records with this objectid, first ensuring that the destination database does not already have an entry with this objectid.
- Once this is done use the following syntax to transfer the diagram :-
|
INSERT INTO databasenew.dbo.dtproperties
(id, objectid, property, value, lvalue, version)
SELECT id, objectid, property, value, lvalue, version
FROM database.dbo.dtproperties
|
- Set the IDENTITY_INSERT property of the 'dtproperties' table back to false by running the query 'SET IDENTITY_INSERT dtproperties OFF'.
- Change the type of the system table 'dtproperties' back to a system by running the query 'UPDATE sysobjects SET xtype='S' WHERE name='dtpropertes''.
- Reset the flag allowing modifications to system tables by checking the properties of the server and uncheck 'Allow modifications to system catalogs'.
|
Sometimes a table may contain duplicate rows, due to a number of reasons. If there are only a few number of duplicate rows then run the following query for each row :-
|
SET ROWCOUNT n /* Where n is the number of duplicate rows - 1 so leaving a single row */
DELETE FROM Table1
WHERE Column1=value
|
If there are many duplicate rows then follow the following steps :-
|
- Select the duplicate key values into a holding table, for example :-
|
SELECT column1, column2, column3=COUNT(*)
INTO HoldingKeyTable
FROM Table1
GROUP BY column1, column2
HAVING COUNT(*)>1
|
- Select the duplicate rows into a holding table,removing the duplicates in the process, for example :-
|
SELECT DISTINCT Table1.*
INTO HoldingDuplicatesTable
FROM Table1, HoldingKeyTable
WHERE Table1.Column1 = HoldingKeyTable.Column1
AND Table1.Column2 = HoldingKeyTable.Column2
|
- Now the HoldingDuplicatesTable should have the unique records.
- Now delete the duplicate rows from the original table :-
|
DELETE Table1
FROM Table1, HoldingKeyTable
WHERE Table1.Column1 = HoldingKeyTable.Column1
AND Table1.Column2 = HoldingKeyTable.Column2
|
- Now put the unique rows back into the original table :-
|
INSERT Table1 SELECT * FROM HoldingDuplicatesTable
|
| Returns specified table column description. | EXEC sp_columns_rowset 'customer' |
| Check to see if a file exists on the specified path. | EXEC @retcode = sp_MSexists_file 'C:\MSSQL7\BIN', 'sproc.sql' |
| Loop through all the databases on the server. | EXEC sp_MSforeachdb @Command="print '?' DBCC CHECKDB ('?')" |
| Loop through all the tables in the database. | EXEC sp_MSforeachtable @Command="print '?' DBCC REINDEX ('?')" |
| Returns table schema. | EXEC sp_MShelpcolumns 'customer' |
| Returns index descriptions of specified table. | EXEC sp_MShelpindex 'customer' |
| Returns index size in KB. | EXEC sp_MSindexspace 'customer' |
| Returns number of rows and size of table. | EXEC sp_MSindexspace 'customer' |
| Returns size of tempdb. | EXEC sp_tempdbspace |
| Returns information on current users and processes. | EXEC sp_who2 'sa' or no login for all active users |
| Check for free disk space in servers fixed disks. | Master..xp_fixeddrives |
| Another method to confirm a file exists | Master..xp_getfiledetails "c:\mssql\binn\sqlservr.exe" |
| Dumps SQL Server's stack to the SQL00001.dmp file in SQL Server \log folder |