DISTINCT and ORDER BY
|
Minimize
usage of the DISTINCT/ORDER BY clause; only use it if necessary.
DISTINCT/ORDER BY
clauses
cause extra work for the database engine and reduce performance. In some rare
cases, ORDER
BY can help
speed up the operation.
|
|||||||||||
CURSORS
|
Using
cursors makes the program slower, as it works against SET-based SQL. Try to
use Temporary
table/Table
variables with an identity column and then iterate all the rows using a WHILE
loop
and
a looping counter, which will map with the identity column.
|
|||||||||||
Calculations &
Convert Functions
|
Avoid
calculations at the left end a WHERE clause. Such calculations don't use the
Index even
if
the Data column has been indexed; instead, they
may do an
Index or Table scan.
For example,
use
SELECT COUNT (*) FROM dbo.SomeLogTable
WHERE DateColumn = '2009-10-11T00:00:00.000'
instead of
SELECT COUNT (*) FROM dbo.SomeLogTable
WHERE CONVERT(CHAR (8), DateColumn, 112) = '20091011’
|
|||||||||||
CAST &
CONVERT
|
Try
to use CAST instead of CONVERT. CAST is ANSI-92 standard, but CONVERT works
in MS SQL server only.
Also,
some CONVERT styles may be deprecated in future MS SQL releases. Use CONVERT
only when you need
to
format the DATETIME data type which CAST cannot do.
|
|||||||||||
Like Operator
|
Try
to avoid wildcard characters at the beginning of a word while searching using
the LIKE keyword,
as
that results in an index scan, which defeats the purpose of an index. The
following statement results
in
an index scan, while the second statement results in an index seek:
SELECT
LocationID FROM Locations WHERE Specialities LIKE ‘%Clinics’
SELECT
LocationID FROM Locations WHERE Specialities LIKE ‘Cl%s’
|
|||||||||||
APPLY joins
|
Use
CROSS/OUTER APPLY when performing JOIN against table valued functions.
Example:
Imagine dbo. FnGetQty() is a table valued function:
SELECT M.ID, M.NAME, C.
PERIOD, C.QTY FROM MASTER M
CROSS APPLY dbo. FnGetQty(M.ID)
C
|
|||||||||||
JOIN Order Sequence
|
The order in
which the tables on your queries are joined have a dramatic effect on how the
query performs.
If your
query happens to join all the large tables and then join to a smaller table
this
can cause a
lot of unnecessary processing and overhead by the SQL Engine
|
|||||||||||
Data Types
|
Try to
define data types to use minimal storage.
·
Do not use the CHAR data type for a Null column. If a
column can
·
Avoid Unicode data types, like NCHAR, NVARCHAR, or
NTEXT. They
Only use
Unicode types if your database will be storing international characters (not
just English letters).
Use these
data types only when they are absolutely needed.
full text index.
|
|||||||||||
Dynamic Queries
|
Try to
minimize usage of dynamic queries. A dynamic query like
SELECT * FROM emp where empid = @eid
is no
problem; you can supply a value for the @eid parameter and there is no
recompilation
of the
execution plan in the database cache. But if you are using a SQL query like :
SELECT * FROM emp where empid = " + @eid
and supply a
parameter (say 100), then the cache will keep the execution plan for the
value of 100 only.
If the ID
changes (to 101), it will recompile the statement, which is a slower action
than the previous example.
However,
when you decide to go with dynamic query, please minimize the usage of concatenation.
|
|||||||||||
Fully
Qualified
Names
|
Always
use the fully qualified name when calling stored procedures.
For
example :
use "EXEC dbo.<Proc_name>"
instead of "EXEC <Proc_name>"
This is a
very common mistake that causes an extra trip to the procedure cache to get
the execution plan.
Also try to
use the schema name while creating a procedure.
CREATE PROCEDURE dbo.<Proc_name>
instead of
CREATE PROCEDURE <Proc_name>
It's good
practice to start with ‘usp_’ to
identify user-defined stored procedures.
|
|||||||||||
Keywords
|
Use
SQL keywords in Capital letters and with Proper indentation to
increase
readability.
|
|||||||||||
Proper
Case While
Coding
|
Although
the SQL environment is not case-sensitive, always be mindful of using the
correct
casing
when referencing object names and field names.
SQL commands
should be in UPPER CASE.
|
|||||||||||
Lock Hints
|
Avoid
using query hints unless you know what exactly you are doing. Specifying
table hints by
using
the WITH keyword.
Support
for use of the READUNCOMMITTED and NOLOCK hints in the Target table
for
UPDATE or DELETE statement will be removed in a future version of SQL Server.
Avoid using
these hints in this context in new development work, and plan to modify
applications
that currently use them.
|
|||||||||||
MERGE Statements
|
Use
MERGE in stored procedures where you would normally perform INSERT, UPDATE
and/or DELETE
against
the same table. This enables you to perform these as a single action. But
also check
the
performance against simple INSERT/UPDATE statements while using for larger
tables.
|
|||||||||||
SELECT Statements
|
Use
only the required number of columns in a SELECT clause, instead of using *.
Using
* returns all columns, which unnecessarily creates a fat record set.
Not
only does it create more overhead and resource wastage, it also considerably
slows down the speed.
|
|||||||||||
SELECT vs. SET
|
|
|||||||||||
SQL-92 Standards
|
Always
follow ANSI 92 join standards. The old syntax will be deprecated
in
a future release of MS SQL Server. Always use explicit joins (such as INNER
JOIN and LEFT OUTER JOIN,
rather
than just JOIN)
For example,
use the following query:
SELECT * FROM employee e1 INNER JOIN employee_dtl e2
ON e1.id = e2.id
instead of
SELECT * FROM employee e1, employee_dtl e2
WHERE e1.id = e2.id
|
|||||||||||
CTE ,Derived Tables, Subqueries
|
When to Use
CTE
Derived
Table
· When you are
required to perform some complex query and result of inner query work
as table for outer query.
Subquery
· When you
require that inner query or condition must be fulfilled before generating any
result.
· Use subquery
when the result that you want requires more than one query and each subquery
provides
a subset of the table involved in the query.
· If the query
requires a NOT EXISTS condition, then you must use a subquery because
NOT EXISTS operator only work with subquery.
|
|||||||||||
Parameter Sniffing
|
The
problem arises with Parameter Sniffing is when a query uses a previously
generated
plan
optimized for a different data distribution. Parameter sniffing performance
problems can affect
all
sorts of queries, but queries that use LIKE
are especially prone to this class of problem.
One
of the Workaround is to assign the
input parameters to Use local variable
while
passing from the Stored procedures.
Before Change
CREATE PROC GetCustOrders (@FirstCust int, @LastCust int)
AS
SELECT CustomerName,SalesItem FROM Sales.SalesOrderHeader
WHERE CustomerID BETWEEN @ FirstCust AND @ LastCust
After Change
CREATE PROC GetCustOrders (@FirstCust int, @LastCust int)
AS
DECLARE @FC int
DECLARE @LC int
SET @FC = @FirstCust
SET @LC = @LastCust
SELECT CustomerName,SalesItem FROM Sales.SalesOrderHeader
WHERE CustomerID BETWEEN @FC AND @LC
|
|||||||||||
Table variables vs.
Temporary Tables
|
If
the result set doesn't contain a vast number of records, stick to a table variable;
otherwise a
temp
table has its advantages. In SQL 2014,
Memory Optimized Table Variable
was
introduced and the variables are only stored in memory. Data Access is more
efficient and
They
don’t use TempDB.
|
|||||||||||
Transaction Scope
|
Try
to minimize the transaction scope within SQL statements. This reduces locking
and
increases application concurrency.
|
|||||||||||
UNION vs UNION ALL
|
Only
Use UNION if you really need to. UNION provides distinct results, but is a
slow process.
If
you already know that the results will be distinct,
use
UNION ALL.
|
|||||||||||
Undocumented
Functionality
|
Do
not use any functionality that is undocumented. You will find many
undocumented
commands on various web sites, but
· Microsoft
will not support them in case of any issues, or
·
Even if it currently supports the command,
Microsoft may stop support in a
future release.
|
|||||||||||
Deprecated, Discontinued
Features
|
With every release of a SQL Server version, Microsoft
announces the ‘Backward
Compatibility’ with prior versions.
This is typically categorized into 4 primary categories —
Deprecated, Discontinued, Breaking and Behavior changes.
If a feature is listed as Deprecated, then it indicates
that Microsoft is stating its disapproval in the usage of
that feature in any future development work. These features
are scheduled to be removed in a future version of SQL Server and hence
during
the review process makes sure that you are not using it in
new application development work.
One
such deprecated feature which lot of legacy applications still use are the
data types NTEXT, TEXT
and
IMAGE. You should avoid using these data types in new development activities
and
plan to modify applications that currently use them. Instead, you can use
NVARCHAR() ,
VARCHAR() and VARBINARY().
Another deprecated syntax is the use of old-style join
syntax (Mentioned above)
|
|||||||||||
SET NOCOUNT ON
|
This
command suppresses the message that shows the number of rows affected by a
SQL statement.
Always
use SET NOCOUNT ON unless you have a very good reason not to; otherwise, this
process
causes extra
network traffic and can impact performance when the procedure is called
frequently.
|
|||||||||||
Usage of Stored
Procedures
|
Whenever a client application needs to send Transact-SQL to
SQL Server,
send
it in the form of a stored procedure instead of a script or embedded Transact-SQL.
Stored
procedures offer many benefits:
and reducing server overhead.
a large binary value into an image data column without using a
stored procedure, it must convert the binary
value
to a character string (doubling its size); when SQL Server receives it, it
must then convert
back
to the binary format. A stored procedure eliminates this overhead, as
parameter values stay in
the
binary format all the way from the application to SQL Server.
by reducing
the amount of code required, along with reducing debugging time.
affecting
clients (assuming you keep the parameters the same and don’t remove any
result-set columns).
This saves developer time.
· Stored
procedures provide better security to your data.
· In Sql
Server 2014 introduced concept of Native Compilation that access
memory-optimized tables
Stored
procedures that are marked with NATIVE_COMPILATION is natively compiled.
This
means the Transact-SQL statements in the procedure are all compiled to native
code
for
efficient execution of performance-critical business logic.
|
|||||||||||
WHERE Clause Hints
|
Try
to avoid IN. While checking the existence of some values, use EXISTS
instead.
IN counts null values, where EXISTS doesn't and returns a simple
Boolean
(Yes/No) rather than returning all values. The result set for IN is
always
heavier than for EXISTS. Example:
SELECT name
FROM emp
WHERE empid IN (SELECT empid FROM empdetails)
returns a
bulkier set of results than
SELECT name
FROM emp
WHERE EXISTS (SELECT 1 FROM empdetails
Where emp. empid = empdetails.
empid)
|
|||||||||||
CLR Routine
|
·
Don’t turn on the CLR unless you will be using
it.
Use
the CLR to complement Transact-SQL code, not to replace it. Version 3
standard data access—such
as SELECT, INSERTS, UPDATES, and DELETEs—are
best done via Transact-SQL, not CLR.
· Computationally
or procedurally intensive business logic can often be encapsulated as
functions
running in the CLR.
· If a
procedure includes both significant data access and computation and logic,
consider separating
the
procedure code in the CLR that calls the Transact-SQL stored procedure that
does most of the data access.
· Use the CLR
for error handling, as it is more robust than what Transact-SQL offers.
· Use the CLR
for string manipulation, as it is generally faster than using Transact-SQL.
· Use the CLR
when you need to take advantage of the large base class library.
· Use the CLR
when you want to access external resources, such as the file system, Event
Log,
a
web service, or the registry.
|
|||||||||||
OUTPUT Clause
|
Always
use a column list in the insert queries. If you need the output of
the
inserted values, use an OUTPUT clause instead of going back to the
database.
Example:
DECLARE @TmpTable TABLE (ID INT, TEXTVal VARCHAR(100))
INSERT TestTable (ID, TEXTVal)
OUTPUT Inserted.ID, Inserted.TEXTVal INTO @TmpTable
SELECT ID, Value FROM TestTable2 where ID=2
select * from @TmpTable
|
|||||||||||
Security
|
While
reviewing the SQL code, try to check for possible scenarios which are
susceptible to SQL Injection
attack
– a security vulnerability issue where malicious code is inserted into
strings and passed to
SQL
server instance for execution.
If you dynamically build your SQL queries by concatenating
strings and not use parameterized queries
or stored procedures, you are susceptible to SQL Injection
attack.
suggest you review your ad hoc SQL queries, and evaluate if it
can be converted into a stored procedure.
|
Venkat's SQL Server Club
"Simple Approach to Address and Solve Complex Issues"
Wednesday, April 22, 2020
Subscribe to:
Posts (Atom)