Category Archives: Optimization

SQL Server Table design and optimization process


Table design and tips in SQL Server

  • Normalize your tables to the third normal form.
    A table is in third normal form (3NF) if it is in second normal form (2NF) and if it does not contain transitive dependencies. In most cases, you should normalize your tables to the third normal form. The normalization is used to reduce the total amount of redundant data in the database. The less data there is, the less work SQL Server has to perform, speeding its performance.

 

  • Consider the denormalization of your tables from the forth or fifth normal forms to the third normal form.
    Normalization to the forth and fifth normal forms can result in some performance degradation, especially when you need to perform many joins against several tables. It may be necessary to denormalize your tables to prevent performance degradation.

 

  • Consider horizontal partitioning of the very large tables into the current and the archives versions.
    The less space used, the smaller the table, the less work SQL Server has to perform to evaluate your queries. For example, if you need to query only data for the current year in your daily work, and you need all the data only once per month for the monthly report, you can create two tables: one with the current year’s data and one with the old data.

 

  • Create the table’s columns as narrow as possible.
    This can reduce the table’s size and improve performance of your queries as well as some maintenance tasks (such as backup, restore and so on).

 

  • Try to reduce the number of columns in a table.
    The fewer the number of columns in a table, the less space the table will use, since more rows will fit on a single data page, and less I/O overhead will be required to access the table’s data.

 

  • Try to use constraints instead of triggers, rules, and defaults whenever possible.
    Constraints are much more efficient than triggers and can boost performance. Constraints are more consistent and reliable in comparison to triggers, rules and defaults, because you can make errors when you write your own code to perform the same actions as the constraints.

 

  • If you need to store integer data from 0 through 255, use tinyint data type.
    The columns with tinyint data type use only one byte to store their values, in comparison with two bytes, four bytes and eight bytes used to store the columns with smallint, int and bigint data types accordingly. For example, if you design tables for a small company with 5-7 departments, you can create the departments table with the DepartmentID tinyint column to store the unique number of each department.

 

  • If you need to store integer data from -32,768 through 32,767, use smallint data type.
    The columns with smallint data type use only two bytes to store their values, in comparison with four bytes and eight bytes used to store the columns with int and bigint data types respectively. For example, if you design tables for a company with several hundred employees, you can create an employee table with the EmployeeID smallint column to store the unique number of each employee.

 

  • If you need to store integer data from -2,147,483,648 through 2,147,483,647, use int data type.
    The columns with int data type use only four bytes to store their values, in comparison with eight bytes used to store the columns with bigint data types. For example, to design tables for a library with more than 32,767 books, create a books table with a BookID int column to store the unique number of each book.

 

  • Use smallmoney data type instead of money data type, if you need to store monetary data values from 214,748.3648 through 214,748.3647.
    The columns with smallmoney data type use only four bytes to store their values, in comparison with eight bytes used to store the columns with money data types. For example, if you need to store the monthly employee payments, it might be possible to use a column with the smallmoney data type instead of money data type.

 

  • Use smalldatetime data type instead of datetime data type, if you need to store the date and time data from January 1, 1900 through June 6, 2079, with accuracy to the minute.
    The columns with smalldatetime data type use only four bytes to store their values, in comparison with eight bytes used to store the columns with datetime data types. For example, if you need to store the employee’s hire date, you can use column with the smalldatetime data type instead of datetime data type.

 

  • Use varchar/nvarchar columns instead of text/ntext columns whenever possible.
    Because SQL Server stores text/ntext columns on the Text/Image pages separately from the other data, stored on the Data pages, it can take more time to get the text/ntext values.

 

  • Use char/varchar columns instead of nchar/nvarchar if you do not need to store unicode data.
    The char/varchar value uses only one byte to store one character, the nchar/nvarchar value uses two bytes to store one character, so the char/varchar columns use two times less space to store data in comparison with nchar/nvarchar columns.

 

  • Consider setting the ‘text in row’ SQL Server 2000 table’s option.
    The text, ntext, and image values are stored on the Text/Image pages, by default. This option specifies that small text, ntext, and image values will be placed on the Data pages with other data values in a data row. This can increase the speed of read and write operations and reduce the amount of space used to store small text, ntext, and image data values. You can set the ‘text in row’ table option by using the sp_tableoption stored procedure.

 

  • If you work with SQL Server 2000, use cascading referential integrity constraints instead of triggers whenever possible.
    For example, if you need to make cascading deletes or updates, specify the ON DELETE or ON UPDATE clause in the REFERENCES clause of the CREATE TABLE or ALTER TABLE statements. The cascading referential integrity constraints are much more efficient than triggers and can boost performance.

How to Optimize Database Replication in SQL Server


 

Optimization and tricks in SQL Server Database Replication

  • Avoid publishing unnecessary data.
    Try to restrict the amount of published data. This can results in good performance benefits, because SQL Server will publish only the amount of data required. This can reduce network traffic and boost the overall replication performance.

 

  • Place the published database log and distribution database log on the separate disk drives.
    Because logging is more write-intensive, it is important that the disk arrays containing the SQL Server log files have sufficient disk I/O performance.

 

  • Do not configure the distribution database to expand or shrink automatically.
    Microsoft recommends to set a fixed size for the distribution database. Setting a database to automatically grow results in some performance degradation, therefore you should set a reasonable initial size of the distribution database.

 

  • Place the distribution component of replication on its own dedicated server.
    This topology is used for performance reasons when the level of replication activity increases or the server resources become constrained. It reduces Publisher loading, but it increases overall network traffic. This topology requires separate Microsoft SQL Server installations, one for the Publisher and one for the Distributor.

 

  • Run the Snapshot Agent as infrequently as possible.
    The Snapshot Agent bulk copies data from the Publisher to the Distributor, which results in some performance degradation. So, try to schedule it during CPU idle time and slow production periods.

 

  • Avoid using continuous replication.
    Try to schedule replication to occur at regular intervals instead of using continuous replication.

 

  • Avoid replicating text, ntext and image columns.
    These data types require more storage space and processing than other column data types.

 

  • Replicate the execution of stored procedures when a large number of rows are affected.
    For example, instead of replicating a very large number of insert, update and delete statements, you can create stored procedure, which will contain all these statements, and replicate to subscriber only the execution of this stored procedure. This can reduce network traffic and boost the overall replication performance.

 

  • Set the “Maximize Throughput for Network Applications” option.
    This can increase SQL Server performance, because Windows NT will allocate more RAM to SQL Server than to its file cache. To set this option, you can do the following:
    1. Double-click the Network icon in Control Panel.
    2. Click the Services tab.
    3. Click Server to select it, and then click the Properties button.
    4. Click Maximize Throughput for Network Applications, and then click OK.
    5. Restart the computer.

 

  • Specify the ‘min server memory’ options.
    This option is used to set a minimum amount of memory allocated to SQL Server. Microsoft recommends that the ‘min server memory’ options be set to at least 16 MB of memory to avoid low memory availability during replication activities, if the server is a remote Distributor or a combined Publisher and Distributor. You can also change these options when SQL Server works on the same computer with other applications. In this case, the ‘min server memory’ option is used to allow SQL Server works when other applications pretend to use all available memory.

 

  • If you work with SQL Server 2000 in a central publisher with remote distributor topology (when the distribution component of replication resides on its own dedicated server) and Publisher connected with the Distributor over slow LAN or WAN, consider compressing the snapshot files.
    This is a new SQL Server 2000 replication feature, which allows you to decrease network traffic by compressing snapshot files.

 

  • Try to enable pull or anonymous subscriptions to increase the Distributor performance.
    This can increase the Distributor performance, because Distribution Agent processing will be moved from the Distributor to Subscribers.

 

  • Increase the MaxBcpThreads property of the Snapshot Agent.
    This property specifies the number of bulk copy operations that can be performed in parallel. By increasing this value, bulk copy operations can run faster, because they will be perform in parallel. To increase the MaxBcpThreads value in the Snapshot Agent profile, you can do the following:
    1. Run SQL Server Enterprise Manager.
    2. Expand a server group; then expand a server.
    3. Expand Replication Monitor; then expand the Agents and click the Snapshot Agents folder.
    4. Right-click appropriate publication and select Agent Profiles…
    5. Click the New Profile button to create the new profile with the appropriate MaxBcpThreads value.
    6. Choose the newly created profile.
    Note. Do not set this property too high, it can results in some performance degradation, because SQL Server will have to spend extra time managing the extra threads. Increase this property to 2 and continue monitoring.

 

  • Set the OutputVerboseLevel property of the Distribution Agent, the Log Reader Agent, the Merge Agent, and the Snapshot Agent to 0.
    This property specifies whether the output should be verbose. There are three available values:
    0 – only error messages are printed
    1 – all of the progress report messages are printed
    2 – all error messages and progress report messages are printed
    The default value is 2. You can increase performance by printed only error messages.
    To set the OutputVerboseLevel value to 0, you can do the following:
    1. Run SQL Server Enterprise Manager.
    2. Expand a server group; then expand a server.
    3. Expand Replication Monitor; then expand the Agents and click the appropriate agent folder.
    4. Right-click appropriate publication and select Agent Properties…
    5. On the Steps tab, double-click the Run agent step, and then add the -OutputVerboseLevel 0 in the Command text box.

 

  • You can minimize the performance affect of history logging by selecting 1 for the HistoryVerboseLevel property of the Distribution Agent, the Log Reader Agent, the Merge Agent, and the Snapshot Agent.
    This property specifies the amount of history logged during distribution operation (for a Distribution Agent), during a log reader operation (for a Log Reader Agent), during a merge operation (for a Merge Agent), or during a snapshot operation (for a Snapshot Agent).
    To set the HistoryVerboseLevel value to 1, you can do the following:
    1. Run SQL Server Enterprise Manager.
    2. Expand a server group; then expand a server.
    3. Expand Replication Monitor; then expand the Agents and click the appropriate agent folder.
    4. Right-click appropriate publication and select Agent Properties…
    5. On the Steps tab, double-click the Run agent step, and then add the -HistoryVerboseLevel 1 in the Command text box.

 

  • If you work with SQL Server 2000 consider using the -UseInprocLoader agent property.
    If this option was set, the in-process BULK INSERT command will be used when applying snapshot files to the Subscriber. You cannot use this property with character mode bcp, this property cannot be used by OLE DB or ODBC Subscribers.
    To set the UseInprocLoader property, you can do the following:
    1. Run SQL Server Enterprise Manager.
    2. Expand a server group; then expand a server.
    3. Expand Replication Monitor; then expand the Agents and click the Distribution Agents or Merge Agents folder.
    4. Right-click appropriate publication and select Agent Properties…
    5. On the Steps tab, double-click the subscription agent step, and then add the -UseInprocLoader property in the Command text box.

 

  • Increase the Log Reader Agent ReadBatchSize parameter.
    This parameter specifies the maximum number of transactions read out of the transaction log of the publishing database. The default value is 500. This option should be used when a large number of transactions are written to a publishing database, but only a small subset of those are marked for replication.

 

  • If you work with transactional replication, increase the Distribution Agent CommitBatchSize parameter.
    This parameter specifies the number of transactions to be issued to the Subscriber before a COMMIT statement is issued. The default value is 100.

 

  • Create an index on each of the columns that is used in the filter’s WHERE clause.
    If you do not use indexes on columns used in filters, then SQL Server must perform a table scan.

 

  • If you work with merge replication, use static instead of dynamic filters.
    Because SQL Server requires more overhead to process the dynamic filters than static filters, for best performance you should use static filters, whenever possible.

How to Optimize Backup and Restore in SQL Server


 

Optimizationd and rules for SQL Backup and Restore, Plans.

 

  • Try to perform backup to the local hard disk first, and copy backup file(s) to the tape later.
    When you perform backup, some SQL Server commands cannot be made, for example: during backup you cannot run ALTER DATABASE statement with either the ADD FILE or REMOVE FILE options, you cannot shrink database, you cannot run CREATE INDEX statement and so on. So, to decrease the backup operation’s time, you can perform backup to the local hard disk first, and then copy backup file(s) to the tape, because tape device usually much more slow than hard disks. The smaller backup operation’s time is, the less impact there will be on the server when the backup occurs.

 

  • Perform backup on multiple backup devices.
    Using multiple backup devices forces SQL Server to create a separate backup thread for each backup device, so the backups will be written to all backup devices in parallel.

 

  • Perform backup on a physical disk array, so the more disks in array the more quickly the backup will be made.
    This can improve performance because a separate thread will be created for each backup device on each disk in order to write the backup’s data in parallel.

 

  • Perform backups during periods of low database access.
    Because backup is very resource effective, try to schedule it during CPU idle time and slow production periods.

 

  • Use full backup to minimize the time to restore databases.
    The full backups take the longest to perform in comparison with differential and incremental backups, but are the fastest to restore.

 

  • Use incremental backup to minimize the time to backup databases.
    The incremental backups take the fastest to perform in comparison with full and differential backups, but are the longest to restore.

 

  • Use differential backup instead of incremental backup when the users update the same data many times.
    Because a differential backup captures only those data pages that have changed after the last database backup, you can eliminate much of the time the server spends rolling transactions forward when recovering transaction logs from the incremental backups. Using differential backup, in this case, can improve the recovery process in several times.

 

  • Try to separate your database to different files and filegroups to backing up only appropriate file/filegroup.
    This can results in smaller backup operation’s time. The smaller backup operation’s time is, the less impact there will be on the server when the backup occurs.

 

  • Use Windows NT Performance Monitor or Windows 2000 System Monitor to check a backup impact on the total system performance.
    You can verify the following counters: SQL Server Backup Device: Device Throughput Bytes/sec to determine the throughput of specific backup devices, rather than the entire database backup or restore operation; SQL Server Databases: Backup/Restore Throughput/sec to monitor the throughput of the entire database backup or restore operation; PhysicalDisk: % Disk Time to monitors the percentage of time that the disk is busy with read/write activity; Physical Disk Object: Avg. Disk Queue Length to determine how many system requests on average are waiting for disk access.

 

  • To decrease the backup operation’s time consider backing up more often.
    The more often you will make backup, the smaller they will be, and the less impact there will be on the server when the backup occurs. So, to avoid locking users for a long time during everyday work, you can perform backup more often.
    Note. The more often you will make backup, the less data you will lost if the database becomes corrupt.

 

  • Place a tape drive on another SCSI bus as disks or a CD-ROM drive.
    The tape drives perform better if they have a dedicated SCSI bus for each tape drive used. Using separate SCSI bus for a tape drive can results in maximum backup performance and prevents conflicts with other drive array access. Microsoft recommends using dedicated SCSI bus for the tape drives whose native transfer rate exceeds 50 percent of the SCSI bus speed.

 

  • Use SQL Server 2000 snapshot backups for the very large databases.
    The SQL Server 2000 snapshot backup and restore technologies work in conjunction with third party hardware and software vendors. The main advantages of snapshot backups and restores are that they can be done in a very short time, typically measured in seconds, not hours, and reduce the backup/restore impact on the overall server performance. The snapshot backups accomplished by splitting a mirrored set of disks or creating a copy of a disk block when it is written and required the special hardware and software.

How to Optimize SQL Stored Procedures


Optimization and rules for SQL Stored Procedures

  •  Use stored procedures instead of heavy-duty queries.
    This can reduce network traffic, because your client will send to server only stored procedure name (perhaps with some parameters) instead of large heavy-duty queries text. Stored procedures can be used to enhance security and conceal underlying data objects also. For example, you can give the users permission to execute the stored procedure to work with the restricted set of the columns and data.

 

  •  Include the SET NOCOUNT ON statement into your stored procedures to stop the message indicating the number of rows affected by a Transact-SQL statement.
    This can reduce network traffic, because your client will not receive the message indicating the number of rows affected by a Transact-SQL statement

 

  •  Call stored procedure using its fully qualified name.
    The complete name of an object consists of four identifiers: the server name, database name, owner name, and object name. An object name that specifies all four parts is known as a fully qualified name. Using fully qualified names eliminates any confusion about which stored procedure you want to run and can boost performance because SQL Server has a better chance to reuse the stored procedures execution plans if they were executed using fully qualified names.

 

  •  Consider returning the integer value as an RETURN statement instead of an integer value as part of a recordset.
    The RETURN statement exits unconditionally from a stored procedure, so the statements following RETURN are not executed. Though the RETURN statement is generally used for error checking, you can use this statement to return an integer value for any other reason. Using RETURN statement can boost performance because SQL Server will not create a recordset.

 

  •  Don’t use the prefix “sp_” in the stored procedure name if you need to create a stored procedure to run in a database other than the master database.
    The prefix “sp_” is used in the system stored procedures names. Microsoft does not recommend to use the prefix “sp_” in the user-created stored procedure name, because SQL Server always looks for a stored procedure beginning with “sp_” in the following order: the master database, the stored procedure based on the fully qualified name provided, the stored procedure using dbo as the owner, if one is not specified. So, when you have the stored procedure with the prefix “sp_” in the database other than master, the master database is always checked first, and if the user-created stored procedure has the same name as a system stored procedure, the user-created stored procedure will never be executed.

 

  • Use the sp_executesql stored procedure instead of the EXECUTE statement.
    The sp_executesql stored procedure supports parameters. So, using the sp_executesql stored procedure instead of the EXECUTE statement improve readability of your code when there are many parameters are used. When you use the sp_executesql stored procedure to executes a Transact-SQL statements that will be reused many times, the SQL Server query optimizer will reuse the execution plan it generates for the first execution when the change in parameter values to the statement is the only variation.

 

  • Use sp_executesql stored procedure instead of temporary stored procedures.
    Microsoft recommends to use the temporary stored procedures when connecting to earlier versions of SQL Server that do not support the reuse of execution plans. Applications connecting to SQL Server 7.0 or SQL Server 2000 should use the sp_executesql system stored procedure instead of temporary stored procedures to have a better chance to reuse the execution plans.

 

  • If you have a very large stored procedure, try to break down this stored procedure into several sub-procedures, and call them from a controlling stored procedure.
    The stored procedure will be recompiled when any structural changes were made to a table or view referenced by the stored procedure (for example, ALTER TABLE statement), or when a large number of INSERTS, UPDATES or DELETES are made to a table referenced by a stored procedure. So, if you break down a very large stored procedure into several sub-procedures, you get chance that only a single sub-procedure will be recompiled, but other sub-procedures will not.

 

  • Try to avoid using temporary tables inside your stored procedure.
    Using temporary tables inside stored procedure reduces the chance to reuse the execution plan.

 

  • Try to avoid using DDL (Data Definition Language) statements inside your stored procedure.
    Using DDL statements inside stored procedure reduces the chance to reuse the execution plan.

 

  •   Add the WITH RECOMPILE option to the CREATE PROCEDURE statement if you know that your query will vary each time it is run from the stored procedure.
    The WITH RECOMPILE option prevents reusing the stored procedure execution plan, so SQL Server does not cache a plan for this procedure and the procedure is recompiled at run time. Using the WITH RECOMPILE option can boost performance if your query will vary each time it is run from the stored procedure because in this case the wrong execution plan will not be used.

 

  • Use SQL Server Profiler to determine which stored procedures has been recompiled too often.
    To check the stored procedure has been recompiled, run SQL Server Profiler and choose to trace the event in the “Stored Procedures” category called “SP:Recompile”. You can also trace the event “SP:StmtStarting” to see at what point in the procedure it is being recompiled. When you identify these stored procedures, you can take some correction actions to reduce or eliminate the excessive recompilations.
%d bloggers like this: