Contents 

Ubitsoft SQL Enlight Online Help

Performance

SA0002 : Variable @variable declared but never used.
SA0003 : Variable @variable used but not previously assigned.
SA0004 : Variable @variable assigned but value never used.
SA0007 : Pattern starting with "%" in LIKE predicate.
SA0009 : Consider using a table variable instead a temporary table.
SA0013 : Avoid returning results in triggers.
SA0016 : Use of very small variable length type (size 1 or 2).
SA0017 : SET NOCOUNT ON option in stored procedures and triggers.
SA0023 : Avoid using inequality operators (<>,!=) in the WHERE clause.
SA0024 : Local cursor not closed.
SA0025 : Local cursor not explicitly deallocated.
SA0026 : Local cursor reference not explicitly deallocated.
SA0027 : Avoid wrapping filtering columns within a function in the WHERE clause.
SA0028 : Deterministic function calls can be extracted from the WHERE clause to avoid unnecessary table scan.
SA0029 : Input parameter never used.
SA0030 : Output parameter never assigned.
SA0032 : Avoid using NOT IN predicate in the WHERE clause.
SA0033 : Don't use the GROUP BY clause without an aggregate function.
SA0040 : Consider moving the column reference to one side of the comparison operator in order to use the column index.
SA0044 : Consider creating indexes on all columns included in foreign keys.
SA0045 : Consider updating statistics as they appear outdated and may mislead the query optimizer.
SA0046 : Consider creating statistics on all composite index columns.
SA0047 : Consider indexing the column as it is used in a WHERE clause or JOIN condition.
SA0048 : Table does not have a primary key.
SA0049 : Table does not have a clustered index.
SA0054 : Avoid modification of parameters in a stored procedure prior to use in a query.
SA0055 : Consider indexing the columns referenced by IN predicates in order to avoid table scans.



Rule: SA0002

Message

Variable @variable declared but never used.

Description

This rule checks for declared neither assigned nor used variables.

Category

Performance

Additional Information

None


Rule: SA0003

Message

Variable @variable used but not previously assigned.

Description

This rule checks for use of not initialized variables.

Category

Performance

Additional Information

None


Rule: SA0004

Message

Variable @variable assigned but value never used.

Description

This rule checks for values assigned to a variable that are either not used or overwriten by new value.

Category

Performance

Additional Information

None


Rule: SA0007

Message

Pattern starting with "%" in LIKE predicate.

Description

This rule checks for for usage of wildcard characters at the beginning of a word while searching using the LIKE keyword.

Usage of wildcard characters at the beggining of a LIKE pattern results in an index scan, which defeats the purpose of an index.

The following two statement results in an index scan, while the third statement results in an index seek:

SELECT     LocationID
FROM       Locations
WHERE      Specialities LIKE '%pples'

SELECT     LocationID
FROM       Locations
WHERE      Specialities LIKE 'A%s'

SELECT     LocationID
FROM       Locations
WHERE      Specialities LIKE 'Ap%'

Category

Performance

Additional Information

None


Rule: SA0009

Message

Consider using a table variable instead a temporary table.

Description

This rule checks for usages of temporary tables that may be replaced by use of table variables. A temporary table that does not have CREATE INDEX is issued on it and is created and dropped in the same batch may be replaced by table variable.

Note that if large data volumes will be inserted in the temporary table it may still be preferred to use temporary tables due to parallel execution restrictions and statistics maintenance.

Example:

CREATE TABLE ##mail
(      
        toAddress NVARCHAR( 100 ) ,
        fromAddres NVARCHAR( 100 ) ,
        subject NVARCHAR( 256 ) ,
        body NVARCHAR( 4000 )
);

INSERT INTO ##mail(  toAddress ,
                          fromAddres ,
                          subject ,
                          body )
VALUES(  'jhonnybravo@cartoonnetwork.com' ,
         'afan@gmail.com' ,
         'Hi' ,
         'Put your subject here.' );

SELECT     toAddress ,
           fromAddres ,
           subject ,
           body
FROM       ##mail

DROP TABLE ##mail;

The above temporary table can be replaced with:

DECLARE @mail AS TABLE(  toAddress NVARCHAR( 100 ) ,
                              fromAddres NVARCHAR( 100 ) ,
                              subject NVARCHAR( 256 ) ,
                              body NVARCHAR( 4000 ) );


INSERT INTO @mail(  toAddress ,
                         fromAddres ,
                         subject ,
                         body )
VALUES(  'jhonnybravo@cartoonnetwork.com' ,
         'afan@gmail.com' ,
         'Hi' ,
         'Put your subject here.' );

SELECT     toAddress ,
           fromAddres ,
           subject ,
           body
FROM       @mail;

Category

Performance

Additional Information

None


Rule: SA0013

Message

Avoid returning results in triggers.

Description

This rule scans triggers to ensure they do not send data back to the caller.

Applications that modify tables or views with triggers do not necessarily expect results to be returned as part of the modification operation. For this reason it is not recommended to return results from within triggers.

This rule flags as not recommended the use of the following statements within a trigger:

PRINT statement
SELECT (without assignment or INTO clause)
FETCH (without assignment)

Category

Performance

Additional Information

None


Rule: SA0016

Message

Use of very small variable length type (size 1 or 2).

Description

This rule checks for use of very small variable length type (ith size of 1 or 2).

It is recommended to use fixed length data type when size is less than 3. Variable length type with size less than 3 consumes more space than the same fixed length type.

Category

Performance

Additional Information

None


Rule: SA0017

Message

SET NOCOUNT ON option in stored procedures and triggers.

Description

This rule scans triggers, stored procedures and functions to ensure they SET NOCOUNT to ON at the beginning.

Use SET NOCOUNT ON at the beginning of your SQL batches, stored procedures and triggers in production environments, as this prevents the sending of DONE_IN_PROC messages and suppresses messages like '(1 row(s) affected)' to the client for each statement in a stored procedure.

For stored procedures that contain several statements that do not return much actual data, setting SET NOCOUNT to ON can provide a significant performance boost, because network traffic is greatly reduced.

Category

Performance

Additional Information

None


Rule: SA0023

Message

Avoid using inequality operators (<>,!=) in the WHERE clause.

Description

The rule checks for usage of the not equal operator in the WHERE clause as it result table and index scans. Consider replacing the not equal operator with equals (=) or inequaluity operators (>,>=,<,<=) if possible.

For example:

SELECT     tleft.c1
FROM       tleft
RIGHT JOIN tright
ON         tleft.c1 = tright.c1
WHERE      tright.c1 <> 2;

You can codify the query to use the column index and still return the same result:

SELECT     tleft.c1
FROM       tleft
RIGHT JOIN tright
ON         tleft.c1 = tright.c1
WHERE      tright.c1 < 2
       AND tright.c1 > 2;

Category

Performance

Additional Information

None


Rule: SA0024

Message

Local cursor not closed.

Description

The rule checks if any local cursor is closed until the end of the batch. Because when open, the cursor still holds locks on referred-to-tables or views, you should explicitly close it as soon as it is no longer needed.

Category

Performance

Additional Information

CLOSE (Transact-SQL)
OPEN (Transact-SQL)


Rule: SA0025

Message

Local cursor not explicitly deallocated.

Description

The rule checks if cursor name is deallocated before the end of the batch using the DEALLOCATE statement.

Category

Performance

Additional Information

DEALLOCATE (Transact-SQL)


Rule: SA0026

Message

Local cursor reference not explicitly deallocated.

Description

The rule checks if cursor variable is deallocated before the end of the batch using the DEALLOCATE statement.

Category

Performance

Additional Information

DEALLOCATE (Transact-SQL)


Rule: SA0027

Message

Avoid wraping filtering columns within a function in the WHERE clause.

Description

When a filtering WHERE clause column is wrapped inside a function, the query optimizer does not see the column and if an index exists on the column, the index most likely will not to be used.

Example 1:

SELECT     *
FROM       users
WHERE      substring(  firstname ,
                       1 ,
                       1 ) = 'm'

Example 2:

SELECT     *
FROM       users
WHERE      firstname LIKE 'm%'

The both statements return the same result, but the first will be slower,because it won't use the column.

Category

Performance

Additional Information

None


Rule: SA0028

Message

Deterministic function calls can be extracted from the WHERE clause to avoid unnecessary table scan.

Description

Consider extracting function calls made in the WHERE clause into local variable, if the function result does not depend on table columns and if it can be evaluated before executing the query. This is necessary, because such function calls can sometimes make the SQL optimizer to perform unnecessary table scan.

Example 1:

SELECT     *
FROM       Production.Product
WHERE      CHECKSUM( N'Bearing Ball' ) = cs_Pname
       AND Name = N'Bearing Ball';

Example 2:

DECLARE @Checksum AS INT

SET @Checksum = CHECKSUM( N'Bearing Ball' )

SELECT     *
FROM       Production.Product
WHERE      @Checksum = cs_Pname
       AND Name = N'Bearing Ball';

The statement in the first exmaple is more likely to perform table scan than the second example.

Category

Performance

Additional Information

None


Rule: SA0029

Message

Input parameter never used.

Description

This rule checks for not used stored procedure or function input paremeters. Unused parameters not necessarily negatively affect the performance, but they just add bloat to your stored procedures and functions.

Category

Performance

Additional Information

None


Rule: SA0030

Message

Output parameter never assigned.

Description

The rule checks for not used stored procedure output parameters. Unused parameters not necessarily negatively affect the performance, but they just add bloat to your stored procedures and functions.

Category

Performance

Additional Information

None


Rule: SA0032

Message

Avoid using NOT IN predicate in the WHERE clause.

Description

Using NOT IN predicate in the WHERE clause generally performs badly, because the SQL Server optimizer has to use a TABLE SCAN instead of an INDEX SEEK even the filtering columns are covered by index. Consider using one of the following options instead all of which offer better performance:

  • EXISTS or NOT EXISTS
  • IN
  • Perform LEFT OUTER JOIN and check for a NULL
SELECT     FirstName ,
           LastName
FROM       Person.Contact AS c
JOIN       HumanResources.Employee AS e
ON         e.ContactID = c.ContactID
WHERE      EmployeeID NOT INSELECT     SalesPersonID
                              FROM       Sales.SalesPerson
                              WHERE      SalesQuota > 250000 )
GO

-- The above statement can be replaced with this one:

SELECT     FirstName ,
           LastName
FROM       Person.Contact AS c
JOIN       HumanResources.Employee AS e
ON         e.ContactID = c.ContactID
WHERE      EmployeeID INSELECT     SalesPersonID
                          FROM       Sales.SalesPerson
                          WHERE      SalesQuota <= 250000 )

Category

Performance

Additional Information

None


Rule: SA0033

Message

Don't use the GROUP BY clause without an aggregate function.

Description

Consider using DISTINCT option instead of using the GROUP BY clause without using aggregate function, because the DISTINCT option will be faster and will give the same end result.

-- Example 1:

SELECT     ColumnA ,
           ColumnB
FROM       T
GROUP BY   ColumnA ,
           ColumnB



-- Example 2:         

SELECT DISTINCT
           ColumnA ,
           ColumnB
FROM       T

Statement in Example 2 will be faster and will return exactly the same result.

Category

Performance

Additional Information

None


Rule: SA0040

Message

Consider moving the column reference to one side of the comparison operator in order to use the column index.

Description

The rule checks for constant to column comparison expressions inside search conditions.

Try to rewrite the comparison expression and move the column on the one side of the comparison operator. This will allow the query optimizer to take advantage of the column index (assuming one is available) instead of performing table scan.

Category

Performance

Additional Information

None


Rule: SA0044

Message

Consider creating indexes on all columns included in foreign keys.

Description

The rule checks for not indexed foreign keys in the current database.

Create an index on any foreign key as the foreign keys are used in joins almost always benefit from having an index.

It is better to create indexes on all foreign keys, despite the possible overhead of maintaining unneeded indexes than not to have index when needed.

Category

Performance

Additional Information

None


Rule: SA0045

Message

Consider updating statistics as they appear outdated and may mislead the query optimizer.

Description

The rule checks the statistics on all tables and indexed views in the current database for outdated statistics.

Evaluation of the statistics can be based on the number of modified rows or on the last time the statistics were updated.

The rules used to evaluate the statistics using the number of modified rows are the same as the rules SQL Server uses to update statistics automatically.

These rules are as follows:

- If a table has 6 or fewer rows, statistics will be updated after 6 changes

- If a table has 500 or fewer rows, statistics will be updated after 500 changes

- If a table has more than 500 rows, statistics will be updated after 20% of the total rows plus 500 rows are modified,added or deleted

Category

Performance

Additional Information

None


Rule: SA0046

Message

Consider creating statistics on all composite index columns.

Description

SQL Server creates statistics only for the first key column of a composite index when the index is created.

The rule checks for all composite index key columns other than the first one, which do not have statistics stored.

Category

Performance

Additional Information

None


Rule: SA0047

Message

Consider indexing the column as it is used in a WHERE clause or JOIN condition.

Description

The rules checks WHERE or JOIN clauses for non-indexed columns staying on the one side of comparison expression. Indexing those columns may improve the query performance.

Category

Performance

Additional Information

None


Rule: SA0048

Message

Table does not have a primary key.

Description

The rule checks all the tables in the current database for having a primary key defined.

Category

Performance

Additional Information

None


Rule: SA0049

Message

Table does not have a clustered index.

Description

The rule checks all the tables in the current database for having a clustered index defined.

Category

Performance

Additional Information

None



Rule: SA0054

Message

Avoid modification of parameters in a stored procedure prior to use in a query.

Description

For best query performance, in some situations you'll need to avoid assigning a new value to a parameter of a stored procedure within the procedure body, and then using the parameter value in a query. The stored procedure and all queries in it are initially compiled with the parameter value first passed in as a parameter to the query.

Category

Performance

Additional Information

None


Rule: SA0055

Message

Consider indexing the columns referenced by IN predicates in order to avoid table scans.

Description

The rule checks for IN predicates that reference non indexed columns. Using columns which do not have index can cause a performance reducing table scan. The following changes will help to avoid this issue: - Add an index to the column referenced by the IN predicate. - Change the IN predicate to reference only indexed columns.

Category

Performance

Additional Information

None