Beruflich Dokumente
Kultur Dokumente
by Dianne Siebold
SYBEX, Network Press, and the Network Press logo are registered trademarks of SYBEX Inc.
Mastering, Expert Guide, Developer’s Handbook, and No experience required. are trademarks of SYBEX Inc.
TRADEMARKS: SYBEX has attempted throughout this book to distinguish proprietary trademarks from descriptive terms by
following the capitalization style used by the manufacturer.
Netscape Communications, the Netscape Communications logo, Netscape, and Netscape Navigator are trademarks of
Netscape Communications Corporation.
Microsoft® Internet Explorer ©1996 Microsoft Corporation. All rights reserved. Microsoft, the Microsoft Internet Explorer logo,
Windows, Windows NT, and the Windows logo are either registered trademarks or trademarks of Microsoft Corporation in
the United States and/or other countries.
The author and publisher have made their best efforts to prepare this book, and the content is based upon final release soft-
ware whenever possible. Portions of the manuscript may be based upon pre-release versions supplied by software manu-
facturer(s). The author and the publisher make no representation or warranties of any kind with regard to the completeness
or accuracy of the contents herein and accept no liability of any kind including but not limited to performance, merchantabil-
ity, fitness for any particular purpose, or any losses or damages of any kind caused or alleged to be caused directly or indi-
rectly from this book.
Photographs and illustrations used in this book have been downloaded from publicly accessible file archives and are used in
this book for news reportage purposes only to demonstrate the variety of graphics resources available via electronic access.
Text and images available over the Internet may be subject to copyright and other rights owned by third parties. Online avail-
ability of text and images does not imply that they may be reused without the permission of rights holders, although the
Copyright Act does permit certain unauthorized reuse as fair use under 17 U.S.C. Section 107.
Copyright ©2000 SYBEX Inc., 1151 Marina Village Parkway, Alameda, CA 94501. World rights reserved. No part of this pub-
lication may be stored in a retrieval system, transmitted, or reproduced in any way, including but not limited to photocopy,
photograph, magnetic or other record, without the prior agreement and written permission of the publisher.
2679c06.qxd 4/18/2000 2:42 PM Page 147
c h a pt e r 6
Optimizing SQL Server
Applications
■ Database Design
■ Profiler
■ Query Analyzer
An excerpt from "Visual Basic Developer's Guide to SQL Server", ISBN # 0-7821-2679-0
Copyright © 2000 SYBEX, Inc., Alameda, CA. www.sybex.com
2679c06.qxd 4/18/2000 2:42 PM Page 148
Whether your application has been in production for years or you’re just now
beginning to design it, performance should be considered in all phases of a project.
Optimizing the way your application interacts with SQL Server has numerous
benefits. The first and foremost benefit is speed—a more efficient application is
faster. Creating an efficient application also means that you write only the code you
need and it performs its job in the most efficient manner. This makes software
leaner and easier to maintain.
There are a number of factors to consider when optimizing a client/server or
multi-tier application: the Visual Basic code, the ADO data access code, and the
SQL Server database itself. Not to mention the client and server hardware as well
as the network environment on which it runs. Consequently, there are a few differ-
ent areas to focus your attention when approaching optimization. The first thing
we’ll cover in this chapter is how database design can affect the performance of an
application. There’s enough database design theory to fill volumes, so I won’t go
into detail on that topic. Instead, I’ll cover the aspects of database design that can
improve performance, such as data types, normalization, and constraints.
SQL Server ships with tools and utilities that can help you troubleshoot appli-
cation bottlenecks and performance. I’ll review SQL Server’s Query Analyzer and
how it’s used to evaluate and optimize queries. Another optimization tool that
ships with SQL Server is Profiler. You’ll find out how to use it to create traces and
apply the results. The Index Tuning Wizard is yet another SQL Server utility that
helps you to create an optimal set of indexes on a database, which can directly
impact the speed of your SQL queries.
Database Design
Database design encompasses a wide range of concepts and techniques used to
structure and organize the data within a database. In this section we’ll examine
the aspects of database design that affect the efficiency and performance of the
database and, in turn, your applications. These points include:
• Data types
• Normalization
• Constraints
An excerpt from "Visual Basic Developer's Guide to SQL Server", ISBN # 0-7821-2679-0
Copyright © 2000 SYBEX, Inc., Alameda, CA. www.sybex.com
2679c06.qxd 4/18/2000 2:42 PM Page 149
The database is the foundation on which applications are built so the importance
of good database design should not be underestimated. The design of the database
has a direct impact on the performance and integrity of your applications. You may
not notice any problems when you have 100 customer records, but when the num-
ber of customer records reaches 100,000, design flaws or a lack of design can
become real problems.
The realm of database design is divided into two specific areas: physical design
and logical design. Physical database design refers to how SQL Server uses the
existing hardware. The way in which a database is partitioned over hard drives is
an example of physical design. Logical database design refers to how a database
is structured and includes consideration of:
• Primary and foreign keys
• Check constraints
• Table design
Once you have a server with plenty of memory, enough disk space, and a fast
processor or two, the next step is to ensure that the database has the best logical
design. Of course, there’s no right way to design a database. In fact, a database
that’s designed well is one that meets the data integrity and performance require-
ments of the applications that use it. For example, a Decision Support System
(DSS) that supplies read-only summary information and makes few data modifi-
cations requires a radically different design than an OLTP application that
requires full transactional integrity and high availability.
Data Types
One of the first things you’ll probably do after creating a database is add a new table
to it. Like most SQL Server functions, this can be done either by issuing T-SQL
commands or through Enterprise Manager. For each column you add to a table
you must provide the column name, data type, length, precision, scale, nullability
default value, and identity information. A column can contain only a single type of
data and its data type defines what kind of data can be stored in it. Table 6.1 lists all
the possible column data types in SQL Server.
An excerpt from "Visual Basic Developer's Guide to SQL Server", ISBN # 0-7821-2679-0
Copyright © 2000 SYBEX, Inc., Alameda, CA. www.sybex.com
2679c06.qxd 4/18/2000 2:42 PM Page 150
The rule of thumb when creating columns is to choose the most efficient data
type depending on the data you need to store.
bit Creates a true/false column; this data type 1/8 of a byte for Boolean
stores only values of 0 or 1. It cannot con- each column, but
tain a null value, so consider carefully when stored in one byte
selecting it whether or not the data in this
column will ever contain a null value.
datetime Precise date field that stores the date and 8 bytes Date
the time accurate to milliseconds.
An excerpt from "Visual Basic Developer's Guide to SQL Server", ISBN # 0-7821-2679-0
Copyright © 2000 SYBEX, Inc., Alameda, CA. www.sybex.com
2679c06.qxd 4/18/2000 2:42 PM Page 151
real Similar to float data type with binary pre- 4 bytes Single
cision up to 7 digits.
smalldatetime Less precise date field stores the date 4 bytes Date
and the time accurate to the minute.
An excerpt from "Visual Basic Developer's Guide to SQL Server", ISBN # 0-7821-2679-0
Copyright © 2000 SYBEX, Inc., Alameda, CA. www.sybex.com
2679c06.qxd 4/18/2000 2:42 PM Page 152
tinyint This data type can contain numbers from 1 byte Integer
0 through 255.
An excerpt from "Visual Basic Developer's Guide to SQL Server", ISBN # 0-7821-2679-0
Copyright © 2000 SYBEX, Inc., Alameda, CA. www.sybex.com
2679c06.qxd 4/18/2000 2:42 PM Page 153
Bit columns are used for true/false data and the value in this column can be only
a 1 or a 0. A bit column cannot contain a null value. If the only possible values for a
column are between 0 and 255, use the tinyint data type because it takes the least
amount of storage. The smallint data type has a range from –32,768 to 32,767. If
you’re not sure what type of numbers will be stored in a column or if there could
potentially be numbers larger than 32,767, select the int data type. By the same
token, there are two floating-point data types: float and real. The float data type
takes 8 bytes of storage and can contain up to 15 decimal places. If this level of
precision isn’t required, use the real data type instead, which can have up to 7
decimal places and takes only 4 bytes of storage.
An excerpt from "Visual Basic Developer's Guide to SQL Server", ISBN # 0-7821-2679-0
Copyright © 2000 SYBEX, Inc., Alameda, CA. www.sybex.com
2679c06.qxd 4/18/2000 2:42 PM Page 154
Bear in mind that how you define the columns in a table may have an impact
on your queries. For example, let’s define a Vendors table:
CREATE TABLE Vendors
(
VendorID int IDENTITY (1, 1) NOT NULL,
VendorName varchar(50) NULL
)
Any SELECT statement that uses the = operator on this column will ignore
the trailing spaces so SELECT * FROM Vendors WHERE VendorName = ‘Acme
Costumes’ returns both records and so will SELECT * FROM Vendors WHERE
VendorName = ‘Acme Costumes ‘.
However, if the LIKE operator is used in the WHERE clause, the trailing spaces
are taken into account in the query . The statement SELECT * FROM Vendors
WHERE VendorName LIKE ‘Acme Costumes’ still returns both records but the SQL
SELECT * FROM Vendors WHERE VendorName LIKE ‘Acme Costumes ‘
now returns only one record.
There is slight overhead incurred when using varchar instead of char because
the size of the data is unknown, but probably not enough to make a difference if
you have sufficient server hardware. Varchar columns can be significantly more
efficient than char columns when SQL Server must do table scans. Because of the
extra spaces that char columns contain, they take up more space. If a query that
requires a table scan is executed, SQL Server may have to read many more pages
if the table contains char columns. A table that is stored on more pages is also less
efficient when it comes to data caching on SQL Server.
An excerpt from "Visual Basic Developer's Guide to SQL Server", ISBN # 0-7821-2679-0
Copyright © 2000 SYBEX, Inc., Alameda, CA. www.sybex.com
2679c06.qxd 4/18/2000 2:42 PM Page 155
in a single unit but instead on linked 8 KB pages. Columns defined with this data
type cannot be indexed, searched, grouped, or ordered (however, you can use
full-text searching on text columns).
The text data type stores data as characters on multiple pages and is used to
store standard character data over 8,000 bytes. The image data type stores graph-
ics from BMP, TIFF, GIF, or JPEG formats or other data in binary format. How-
ever, the image itself is not visible in SQL Server. It’s up to the client application
to interpret and display the image. The following query selects an image and text
column with the abridged output:
SELECT EmployeeID, Notes, Photo
FROM Employees
An excerpt from "Visual Basic Developer's Guide to SQL Server", ISBN # 0-7821-2679-0
Copyright © 2000 SYBEX, Inc., Alameda, CA. www.sybex.com
2679c06.qxd 4/18/2000 2:42 PM Page 156
One common use for a user-defined data type is storing a Social Security Num-
ber. Call the stored procedure sp_addtype in T-SQL to create this data type:
sp_addtype SSN, ‘VARCHAR(11)’, ‘NOT NULL’
TIP Calling sp_addtype creates the new data type and adds it to the systypes table.
The systypes table contains a row for each data type with its name, base data
type, precision, and other information about it. To find out what user-defined
data types exist in a database call the sp_datatype_info stored procedure.
A column defined with the above user-defined data type can store a standard
9-digit SSN in 999-99-9999 format. You can also create a user-defined data type in
Enterprise Manager by following these steps:
1. Expand the tree down to the database level.
2. Right-click the User Defined Data Types icon.
3. Select New User Defined Data Type.
4. Enter the name, base data type, and other details in the dialog. This screen,
shown in Figure 6.1, allows you to enter additional information like an asso-
ciated rule or default constraint (unfortunately check constraints must be
defined individually when creating a table).
5. Click OK.
An excerpt from "Visual Basic Developer's Guide to SQL Server", ISBN # 0-7821-2679-0
Copyright © 2000 SYBEX, Inc., Alameda, CA. www.sybex.com
2679c06.qxd 4/18/2000 2:42 PM Page 157
FIGURE 6.1:
Creating a user-defined
data type
A user-defined data type is used just like any other data type when creating a
table. It’s available in the dropdown list of data types when you create a table in
Enterprise Manager, which also displays its base data type. You can also use it
when creating tables in T-SQL:
CREATE TABLE Employee
(
EmployeeID INT PRIMARY KEY IDENTITY,
SSN SSN,
CHECK ([SSN] LIKE ‘[0-9][0-9][0-9]-[0-9] _
[0-9]-[0-9][0-9][0-9][0-9]’)
)
TIP If you use the SSN column in an index, you can create a more efficient column by
using int as the base data type. This reduces the size of the column from 11 to 4
and makes indexing and data retrieval more efficient. Also, the check constraint
becomes unnecessary. The trade-off for this efficiency is having to format the
value on the client each time.
An excerpt from "Visual Basic Developer's Guide to SQL Server", ISBN # 0-7821-2679-0
Copyright © 2000 SYBEX, Inc., Alameda, CA. www.sybex.com
2679c06.qxd 4/18/2000 2:42 PM Page 158
Normalization
Normalization is a series of guidelines applied to the design of a database to sep-
arate data. There are actually up to five levels (called forms) of normalization,
and we’ll cover the first three because they’re the most common. Normalization
essentially eliminates duplicate data in a database, which makes updates easier
because they only have to occur in one place. On the other hand, querying a fully
normalized database might require numerous table joins.
First Normal Form states that tables cannot contain any repeating values or
multi-value columns. A violation of First Normal Form would be a table of orders
that has columns like Quantity1, OrderAmount1, Quantity2, and OrderAmount2,
as shown in Figure 6.2.
This design lacks flexibility and is inefficient for retrieving data. Even if it meets
your current business needs, this table will most certainly need to be redesigned
as soon as columns Quantity3 and OrderAmount3 are required. To maintain First
Normal Form this table should be decomposed into a master Orders table, with
the OrderID and OrderDate fields, and an OrderDetails table, with OrderID,
Quantity, and OrderAmount fields, as shown in Figure 6.3.
108 28 280.00
108 2/9/00
108 5 10,000.00
An excerpt from "Visual Basic Developer's Guide to SQL Server", ISBN # 0-7821-2679-0
Copyright © 2000 SYBEX, Inc., Alameda, CA. www.sybex.com
2679c06.qxd 4/18/2000 2:42 PM Page 159
A table with an EmployeeName column that contains the employee’s first and
last names is also a violation of First Normal Form because it contains multiple
values. A better design would be to create separate columns called FirstName
and LastName.
Second Normal Form stipulates that tables must contain data about a single entity
and each non-key column is dependent on the entire primary key. A violation of
Second Normal Form would be a table that contains both order information and
shipper information, like Figure 6.4.
FIGURE 6.4:
OrderID OrderDate ShipperID ShipperName ShipperPhone
A table that violates
Second Normal Form 108 2/9/00 3 BDS Express 858-333-0303
This table design wastes space because the shipper data is stored redundantly
for each order. In addition, if the shipper phone number changes, it must be
updated in every order record. This design also violates Second Normal Form
because the shipper columns are not related in any way to the OrderID primary
key column. To implement Second Normal Form, create a primary key for every
table and ensure that each non-key column in the table is dependent on the pri-
mary key. The shipper data in this example should be moved into a separate
related table, as shown in Figure 6.5.
FIGURE 6.5:
Tables in Second
Normal Form OrderID OrderDate ShipperID
108 2/9/00 3
109 2/9/00 3
An excerpt from "Visual Basic Developer's Guide to SQL Server", ISBN # 0-7821-2679-0
Copyright © 2000 SYBEX, Inc., Alameda, CA. www.sybex.com
2679c06.qxd 4/18/2000 2:42 PM Page 160
Third Normal Form states that all non-key columns be mutually independent.
In other words, a non-key column may not depend on another non-key column.
An example of a column that violates Third Normal Form is a calculated column.
A change to a column on which a calculated column is based means that both
the modified column and the calculated column will change and more than one
column is affected by a single change. For example, if you have a column called
CelsiusTemp that’s calculated from the FahrenheitTemp column, then each time
the FahrenheitTemp column is modified the CelsiusTemp column is also modi-
fied. Ideally, calculated data should never be stored in a database (although
sometimes common sense overrides these rules, as we’ll see later on).
An excerpt from "Visual Basic Developer's Guide to SQL Server", ISBN # 0-7821-2679-0
Copyright © 2000 SYBEX, Inc., Alameda, CA. www.sybex.com
2679c06.qxd 4/18/2000 2:42 PM Page 161
run a nightly batch job that calculates the total of all the orders and updates the
Customers table.
FIGURE 6.6:
OrderID OrderDate CustomerID ShipperID
Joins required for a query
against a normalized
database 108 2/9/00 500 3
ShipperID ShipperName
3 BDS Express
FIGURE 6.7:
OrderID OrderDate CustomerID CustomerName ShipperID ShipperName
A query against a denor-
malized database requires
Three Jewels BDS Express
fewer table joins. 108 2/9/00 500 Imports 3
108 28 280.00
108 5 10,000.00
An excerpt from "Visual Basic Developer's Guide to SQL Server", ISBN # 0-7821-2679-0
Copyright © 2000 SYBEX, Inc., Alameda, CA. www.sybex.com
2679c06.qxd 4/18/2000 2:42 PM Page 162
The point to remember when it comes to normalization is that the rules must
be used to fit the requirements of the application. If a particular query requires an
eight-table join, it may be a better decision to store some redundant data. Updat-
ing this data will incur some additional overhead, but it may be worth the cost for
better query performance. Your users probably don’t care if the database is fully
normalized—they just want it to be responsive!
Keys
Primary and foreign key constraints are two of the bare essentials when it comes
to implementing good database design. The benefits of good design include data
integrity, performance, and scalability. We’ll first look at the primary key, which is
a SQL Server constraint that consists of one or more columns and guarantees that
each record in a table is unique. When you create a primary key, SQL Server inter-
nally creates a unique index on the selected column(s) and a row is inserted into
the sysobjects and sysindexes system tables. Simplicity and stability are the
attributes to look for in a column when selecting a primary key. Ideally, the pri-
mary key column(s) should be narrow. For example, a single column of data type
int creates a smaller index than three varchar columns.
It’s important for the primary key to be as compact and as fast as possible
because it will be used frequently in table joins and queries. A smaller primary
key is also important because in SQL Server a table’s clustered index key is used
as a row locator by all non-clustered indexes. The primary key columns must also
be stable with no data fluctuations. This is necessary because relationships are
built between tables based on primary keys, so the data values shouldn’t change.
Because creating a primary key creates a unique index, you must specify
whether it should create a clustered or non-clustered index.
• A clustered index sorts the actual rows in a table based on the values of the
primary key columns. There can be only one clustered index per table.
• A non-clustered index is stored separately from the table and the underly-
ing rows in the table are unchanged. Therefore you can have more than one
non-clustered index per table.
An excerpt from "Visual Basic Developer's Guide to SQL Server", ISBN # 0-7821-2679-0
Copyright © 2000 SYBEX, Inc., Alameda, CA. www.sybex.com
2679c06.qxd 4/18/2000 2:42 PM Page 163
provide the starting ID (the Identity Seed value) and the number to increment
each new ID by (the Identity Increment), and a new value for the column is gener-
ated whenever a record is inserted. Remember that the automatic generation of
values in an identity column can be disabled, so the identity property itself doesn’t
guarantee a unique number.
One practice to avoid is that of creating a primary key that has meaning. For
example, if you have an Orders table you might want to create a primary key col-
umn based on the customer’s ID number, their state code, and the date of the
order. The key value for customer 1234 based in New York that placed an order
on 3/15/00 would be 1234NY031500. Some of the benefits of this approach are
the ability to sort orders by a particular customer and use the key in other logic.
However, this method can quickly lead to problems. A customer could move to
another state, which changes the primary key value. Or if the customer creates a
subdivision with a separate customer number, any logic that retrieves or sorts
records on this value won’t access the records for the new subdivision. This type
of primary key is also very long and contains alphanumeric data so it’s not as effi-
cient as an identity column.
To find out the primary key column for a table, call the sp_pkeys stored proce-
dure. You can also call sp_helpindex to find out all the indexes (including the
primary key index) for a table. Here’s the syntax to return this information for the
Orders table and the abridged output:
sp_helpindex Orders
Foreign Keys
In the relational model, relationships are created between tables through both pri-
mary and foreign key constraints. A foreign key is a column (or columns) in a child
table that is the same as a primary key column in the parent table, thus creating a
relationship between the two tables. The primary function of this constraint is to
enforce referential integrity. Referential integrity preserves the relationship between
An excerpt from "Visual Basic Developer's Guide to SQL Server", ISBN # 0-7821-2679-0
Copyright © 2000 SYBEX, Inc., Alameda, CA. www.sybex.com
2679c06.qxd 4/18/2000 2:42 PM Page 164
tables when records are inserted or deleted. For example, in the Northwind data-
base, the Orders table has a foreign key of CustomerID and is related to the Cus-
tomers table through its primary key column CustomerID. To maintain referential
integrity, an order cannot be added to the Orders table for a customer that doesn’t
exist in the Customers table. By the same token, you cannot delete a Customer
(the parent) without first deleting its associated orders (the children) because this
destroys the relationship between the tables. Figure 6.8 illustrates how tables are
related by their keys.
A table can have multiple foreign keys, and SQL Server doesn’t create an index
on a foreign key column. You may want to create indexes on foreign key columns
because they’ll most likely be used in table joins and the correct indexes will
improve performance. The more foreign keys you have on a table, the more over-
head you’ll have on INSERT, UPDATE, and DELETE operations. The execution
plan will contain additional steps for each foreign key. This is because SQL Server
must check the foreign key value to ensure that integrity is maintained. For example,
if you attempt to insert an order in the Orders table with a Customer ID value
that doesn’t exist in the Customers table, SQL Server will raise an error and you’ll
be unable to add the new record.
Constraints
Constraints enforce data integrity and ensure the quality of the data in your
database. Not only do constraints enable your database to run more efficiently,
but they also result in less work for front-end developers. Constraints are espe-
cially helpful in ensuring data integrity by validating column data. Because
An excerpt from "Visual Basic Developer's Guide to SQL Server", ISBN # 0-7821-2679-0
Copyright © 2000 SYBEX, Inc., Alameda, CA. www.sybex.com
2679c06.qxd 4/18/2000 2:42 PM Page 165
these checks occur in the database, developers aren’t responsible for imple-
menting these validations in client applications.
Default constraints specify the value of a column if no value is supplied when
the record is inserted. If the majority of your customers are located in the United
States, you might create a default constraint that enters the value USA in the
country column of a CustomerAddress table. Default constraints add little over-
head to an insert operation so they can be used without worrying about a perfor-
mance hit.
NOTE You can insert a record in a table whose columns all contain default values with
the syntax INSERT TableName DEFAULT VALUES. The DEFAULT VALUES informs the
insert to use the default values for columns that have them.
Default constraints are useful because they ensure that a column will always
have data when a row is added. This is also beneficial to front-end developers
because they can count on the presence of data in columns.
Check constraints are defined at the column level and specify the allowable val-
ues for that column. Check constraints execute automatically when data is either
inserted or updated. A check constraint expression must evaluate to true or
unknown in the case of nulls. If a check constraint evaluates to false, the opera-
tion fails. A check constraint could be used to ensure that a column value is
within a given range:
TotalMileage BETWEEN 0 AND 1000
You can use SQL Server’s built-in functions such as GETDATE(), arithmetic
operators, and the expressions IN, AND, OR, NOT, and LIKE.
Sex IN (‘M’, ‘F’)
SSN LIKE ‘[0-9] [0-9] [0-9]- [0-9] [0-9]- [0-9] [0-9] [0-9] [0-9] ‘
An excerpt from "Visual Basic Developer's Guide to SQL Server", ISBN # 0-7821-2679-0
Copyright © 2000 SYBEX, Inc., Alameda, CA. www.sybex.com
2679c06.qxd 4/18/2000 2:42 PM Page 166
constraints shouldn’t conflict with your check constraints. For example, if the
default constraint puts the value 2 in a column but the check constraint specifies
that the column value must be between 5 and 10, INSERT operations that use the
default will fail.
Call the sp_helpconstraint stored procedure to query the constraints that exist
for a single table. The syntax sp_helpconstraint Employees returns the con-
straint name, type, status, and keys for the table as well as the names of any tables
that reference that table through foreign keys.
Indexes
Table indexes are an excellent way to improve query performance. There is some
overhead in maintaining indexes because they must be updated as records are
added or deleted. Consequently, indexes have an adverse effect on data modifica-
tion operations. An index can be either clustered or non-clustered and each type
affects performance differently.
Both clustered and non-clustered indexes are organized as B-trees (the B stands
for balanced). However, clustered indexes reference the key value directly. There-
fore the data in a table is physically sorted in the order of the index key values.
Non-clustered indexes are stored separately from the data in the table. Each key
value in the non-clustered index also contains a bookmark to the page where the
row is located. SQL Server searches a non-clustered index to find records that
match a query and uses the bookmark to find the data. If the table is sorted by an
existing clustered index, it retrieves the value directly from the clustered key
value. Because a clustered index orders the rows in a table there can be only one
per table.
Each table should contain a clustered index and by default the primary key
columns will create a clustered index. Clustered indexes provide optimal perfor-
mance for queries that specify a range in the WHERE clause. Clustered indexes
are most useful for queries that are less selective. This is because a clustered index
actually scans the pages where data is located. Situations that call for a clustered
index include:
• Queries that return a range of values returned by a WHERE clause that con-
tains the operators BETWEEN, >, >=, <, <=
• Queries that return a large result set
An excerpt from "Visual Basic Developer's Guide to SQL Server", ISBN # 0-7821-2679-0
Copyright © 2000 SYBEX, Inc., Alameda, CA. www.sybex.com
2679c06.qxd 4/18/2000 2:42 PM Page 167
Profiler 167
• Columns that contain a limited set of unique values like a state column or a
status column
• Primary key columns
A non-clustered index is useful for highly selective queries because it can quickly
eliminate values based on the index key value. For rows that are included in the
query result set, it must navigate to the data page to read the data. Non-clustered
indexes should be used for:
• Queries that return small result sets
• Columns referenced in the WHERE clause that return exact matches
• Columns that contain highly distinct values like a company name column
• Columns involved in JOIN and GROUP operations
• Foreign key columns
Profiler
Profiler is a utility that ships with SQL Server and is used to monitor events gen-
erated by the SQL Server engine. These events are raised by various operations
that take place on the server whether they are initiated by a client application,
from within Query Analyzer, or from some other source. For example, when a
user connects to a database, an event is generated. The occurrence of this event
can be tracked by Profiler.
There are approximately 60 different events that can be detected by Profiler and
each of these events falls under one of 11 different event class categories. Now I’ll
take you through the steps required to create a trace definition. Following that I’ll
detail the different types of events that you can monitor using Profiler and what
those events tell you.
An excerpt from "Visual Basic Developer's Guide to SQL Server", ISBN # 0-7821-2679-0
Copyright © 2000 SYBEX, Inc., Alameda, CA. www.sybex.com
2679c06.qxd 4/18/2000 2:42 PM Page 168
FIGURE 6.9:
Creating a new trace in
Profiler
2. On the General tab, enter the name of the trace and select the Private trace
type. The trace type specifies where the trace definition resides. If you select
Private, the trace is stored in the local registry under HKEY_CURRENT_USER\
Software\Microsoft\MSSQLServer\SQLServerProfiler\Queries\.
Shared traces are stored in the server’s registry, so you must be connected as
a user that has the appropriate access rights.
3. Pick the SQL Server Server whose events you want to monitor.
An excerpt from "Visual Basic Developer's Guide to SQL Server", ISBN # 0-7821-2679-0
Copyright © 2000 SYBEX, Inc., Alameda, CA. www.sybex.com
2679c06.qxd 4/18/2000 2:42 PM Page 169
Profiler 169
4. Select the Capture To File option and provide a directory and file name to
save the trace. By default all trace results are displayed in the Profiler win-
dow. This screen allows you to select to save the trace results to a file or a
table. Remember that this data is saved as a trace file with a .trc extension.
Saved trace sessions can be replayed later or used as a workload file for the
Index Tuning Wizard. You can specify the maximum file size in megabytes for
the trace file or the maximum number of rows in thousands for a trace table.
5. Click on the Events tab to specify which events you want to monitor. You
can see this tab in Figure 6.10. By default, the Sessions events and the TSQL
RPC:Completed and SQL:BatchCompleted events are included. Add the
SP:CacheMiss, SP:Starting, and SP:StmtStarting events to the Selected
events list box. These events will display under these circumstances:
• When users connect and disconnect from SQL Server
• When stored procedures are not started from the cache, when a stored
procedure is started, and when individual stored procedure statements
are started
• When an RPC call is completed and when a SQL batch is completed
FIGURE 6.10:
The Events tab in Profiler
An excerpt from "Visual Basic Developer's Guide to SQL Server", ISBN # 0-7821-2679-0
Copyright © 2000 SYBEX, Inc., Alameda, CA. www.sybex.com
2679c06.qxd 4/18/2000 2:42 PM Page 170
6. Click on the Data Columns tab to add or remove columns to appear in the
Profiler window. You can also select columns to group the results by. For
this example, let’s add the Event Sub Class to the Selected data list box, as in
Figure 6.11. For each event that Profiler monitors, it will also display that
event’s sub class in the Profiler window and in the trace file.
FIGURE 6.11:
The Data Columns tab in
Profiler
7. Click on the Filters tab to narrow down the trace results. This is where we
can specify which user’s activity to monitor. Click on the SQL User Name
node and enter the user name in the Include box, as shown in Figure 6.12.
Profiler will now only include events generated by that SQL user name.
The Profiler tool also generates events on SQL Server and by default it
excludes any events raised by the application SQL Server Profiler. This
means that activity generated by the Profiler won’t be visible in a trace.
Filtering can be quite powerful and it allows you to monitor events initi-
ated by a single user or a single application. This is useful if you want to
An excerpt from "Visual Basic Developer's Guide to SQL Server", ISBN # 0-7821-2679-0
Copyright © 2000 SYBEX, Inc., Alameda, CA. www.sybex.com
2679c06.qxd 4/18/2000 2:42 PM Page 171
Profiler 171
FIGURE 6.12:
The Filters tab in Profiler
8. Click OK to save the trace. To run the new trace, select File ➢ Run Traces
and select the new trace from the list box. Remember that this trace is saving
its results to a file so you’ll want to monitor the length of time it remains
running.
9. Open up Query Analyzer, connect as the user you selected to include, select
the Northwind database, and call the stored procedure [Employee Sales
By Country] ‘01/01/96’, ‘01/01/98’. You’ll see all the events generated
by this activity and the Profiler window will look similar to Figure 6.13.
An excerpt from "Visual Basic Developer's Guide to SQL Server", ISBN # 0-7821-2679-0
Copyright © 2000 SYBEX, Inc., Alameda, CA. www.sybex.com
2679c06.qxd 4/18/2000 2:42 PM Page 172
FIGURE 6.13:
The results of the
Profiler trace
Trace Events
Trace events, also called event classes, are the operations that occur on SQL
Server that can be monitored by Profiler. For example, the Connect event occurs
on the server when a user successfully connects to SQL Server. The trace events
you specify in Profiler determine when event information is retrieved; the data
columns you specify determine what information about those events is captured.
An excerpt from "Visual Basic Developer's Guide to SQL Server", ISBN # 0-7821-2679-0
Copyright © 2000 SYBEX, Inc., Alameda, CA. www.sybex.com
2679c06.qxd 4/18/2000 2:42 PM Page 173
Profiler 173
Execution Warnings Warnings have occurred during the execution of a stored procedure or
SQL statement.
Missing Join Predicate The SQL query currently being executed is missing a join predicate.
Sort Warnings The sort operations for a query’s ORDER BY clause exceed the available
memory. This sort doesn’t include the creation of indexes.
An excerpt from "Visual Basic Developer's Guide to SQL Server", ISBN # 0-7821-2679-0
Copyright © 2000 SYBEX, Inc., Alameda, CA. www.sybex.com
2679c06.qxd 4/18/2000 2:42 PM Page 174
Lock:Acquired A lock has been placed on a row, page, extent, table, or database.
Lock:Deadlock Two transactions have deadlocked. This occurs when Transaction1 has a lock
on an object and is trying to access another object. Transaction2 has a lock
on that object and won’t release it until it can access the object that Transac-
tion1 has locked.
Lock:Escalation A more selective lock has been converted to a less selective lock. For example,
a row lock was converted to a page lock.
Lock:Released A lock on a row, page, extent, table, or database has been released.
Lock:Timeout A lock request that has been blocked by another lock has timed out.
Auto-UpdateStats An error or success event was raised during the automatic updating of
index statistics.
Exec Prepared SQL A prepared stored procedure or SQL statement has been executed.
An excerpt from "Visual Basic Developer's Guide to SQL Server", ISBN # 0-7821-2679-0
Copyright © 2000 SYBEX, Inc., Alameda, CA. www.sybex.com
2679c06.qxd 4/18/2000 2:42 PM Page 175
Profiler 175
Server Memory Change Server memory usage has increased or decreased by either 1 MB or 5% of
the server’s total memory (whichever is greater).
ServiceControl A server control event occurred. This event is raised when the SQL Server
service is exited, started, paused, continued, or stopped.
Each of these events has an event sub class that’s used to identify what type of
scan has occurred (see Table 6.8).
1 Normal
2 First
4 Back
8 Unordered
16 No Data
32 Reserved
64 Exlatch
256 Marker
ExistingConnection Activity by users that were connected to the server before the trace was started
occurred.
An excerpt from "Visual Basic Developer's Guide to SQL Server", ISBN # 0-7821-2679-0
Copyright © 2000 SYBEX, Inc., Alameda, CA. www.sybex.com
2679c06.qxd 4/18/2000 2:42 PM Page 177
Profiler 177
example, if you issue a statement to INSERT a record into a table, Profiler will cap-
ture the event even if a constraint violation occurs and the actual operation fails.
SP:CacheMiss A stored procedure was not found in the cache after its attempted execution.
SP:ExecContextHit The execution context for a stored procedure that executed was found in the cache.
SP:StmtCompleted A SQL statement within a stored procedure has completed. (This event is raised for
each statement inside a stored procedure.)
SP:StmtStarting A SQL statement within a stored procedure has started. (This event is raised for each
statement inside a stored procedure.)
An excerpt from "Visual Basic Developer's Guide to SQL Server", ISBN # 0-7821-2679-0
Copyright © 2000 SYBEX, Inc., Alameda, CA. www.sybex.com
2679c06.qxd 4/18/2000 2:42 PM Page 178
WARNING Stored procedure events monitor the execution of all stored procedures, including
the system stored procedures that SQL Server calls when you open Query Analyzer
or Enterprise Manager. Therefore, the trace file or table can grow very quickly
unless you filter out only the stored procedure events for a particular application
or user.
DTCTransaction A transaction that’s managed by the DTC (an MTS transaction for example) has
occurred.
An excerpt from "Visual Basic Developer's Guide to SQL Server", ISBN # 0-7821-2679-0
Copyright © 2000 SYBEX, Inc., Alameda, CA. www.sybex.com
2679c06.qxd 4/18/2000 2:42 PM Page 179
Profiler 179
These events all monitor T-SQL statements executed on SQL Server whether
they’re issued via RPC, a batch of statements, or a single statement. RPC packets are
optimized for performance and some components will use RPC as the mechanism
for sending T-SQL commands to SQL Server. For example, the OLE DB Provider for
SQL Server and the ODBC SQL Server Driver use RPC to issue stored procedures
or SQL commands. Therefore, if you run Profiler and you have an application using
ADO, you’ll most likely see RPC events appear in Profiler. Conversely, if you issue
T-SQL commands from Query Analyzer, you’ll see standard T-SQL batch and state-
ment events.
Trace Wizard
Another useful feature in Profiler is the Create Trace Wizard. This wizard steps
you through creating a trace to identify one of six common problems:
• Find the worst performing queries
• Identify scans of large tables
• Identify the cause of a deadlock
• Profile the performance of a stored procedure
• Trace Transact-SQL activity by application
• Trace Transaction-SQL activity by user
The Trace Wizard is accessed from the main menu by selecting Tools ➢ Create
Trace Wizard. You can step through the wizard to create a definition and then
tweak it to create your own custom queries.
An excerpt from "Visual Basic Developer's Guide to SQL Server", ISBN # 0-7821-2679-0
Copyright © 2000 SYBEX, Inc., Alameda, CA. www.sybex.com
2679c06.qxd 4/18/2000 2:42 PM Page 180
An excerpt from "Visual Basic Developer's Guide to SQL Server", ISBN # 0-7821-2679-0
Copyright © 2000 SYBEX, Inc., Alameda, CA. www.sybex.com
2679c06.qxd 4/18/2000 2:42 PM Page 181
server suffers from poor performance you can save them and replay them
on another server to test the comparative performance.
Query Analyzer
SQL Server’s Query Analyzer is a tool that provides a graphical user interface for
editing and running T-SQL statements interactively. You can get to the Query
Analyzer from inside Enterprise Manager or Profiler. With the Query Analyzer
you can:
• Open, edit, and save queries
• Execute T-SQL queries, commands, or stored procedures
• View query or command results
• View the execution plan for a query
• View suggestions for indexes and statistics
An excerpt from "Visual Basic Developer's Guide to SQL Server", ISBN # 0-7821-2679-0
Copyright © 2000 SYBEX, Inc., Alameda, CA. www.sybex.com
2679c06.qxd 4/18/2000 2:43 PM Page 182
FIGURE 6.14:
The execution plan in
Query Analyzer
FIGURE 6.15:
The tool tip gives you addi-
tional information about a
step in the execution plan.
An excerpt from "Visual Basic Developer's Guide to SQL Server", ISBN # 0-7821-2679-0
Copyright © 2000 SYBEX, Inc., Alameda, CA. www.sybex.com
2679c06.qxd 4/18/2000 2:43 PM Page 183
You can use the Query Analyzer to test your queries against the tables in your
database as they are. By adding indexes or perhaps restructuring the query, you
may be able to improve performance, which you can identify by examining the
new execution plan. For example, if you ran the Employee Sales By Country
stored procedure and the Employees table did not have a primary key index, the
execution plan would look like Figure 6.16.
An excerpt from "Visual Basic Developer's Guide to SQL Server", ISBN # 0-7821-2679-0
Copyright © 2000 SYBEX, Inc., Alameda, CA. www.sybex.com
2679c06.qxd 4/18/2000 2:43 PM Page 184
FIGURE 6.16:
Query execution plan when
the Employees table has no
primary key index
An excerpt from "Visual Basic Developer's Guide to SQL Server", ISBN # 0-7821-2679-0
Copyright © 2000 SYBEX, Inc., Alameda, CA. www.sybex.com
2679c06.qxd 4/18/2000 2:43 PM Page 185
FIGURE 6.17:
Query execution plan for
the Employees table with a
primary key index
An excerpt from "Visual Basic Developer's Guide to SQL Server", ISBN # 0-7821-2679-0
Copyright © 2000 SYBEX, Inc., Alameda, CA. www.sybex.com
2679c06.qxd 4/18/2000 2:43 PM Page 186
FIGURE 6.18:
Index analysis from inside
the Query Analyzer
The Index Tuning Wizard recommends a set of indexes for a single database
based on a workload file. The workload can be a SQL script or a Profiler trace saved
to a file or table. If you use Profiler to create a workload for the Index Tuning Wiz-
ard, it should contain the RPC, SQL, and SQL Batch Starting or Completed events.
Run the Profiler to capture all the SQL calls to the database for a period of time.
This gives you a file that contains activity representative of the standard workload
on a database.
The Index Tuning Wizard is accessed by selecting it from the Management
Category in the Enterprise Manager’s Tools ➢ Wizards menu. The first screen
appears and you select the server and the database (see Figure 6.19). If you select the
option to Keep all existing indexes, the Index Tuning Wizard recommends only new
indexes and won’t recommend dropping existing indexes. If you select Perform
thorough analysis, the Index Tuning Wizard does a complete analysis of the work-
load you provide for the most complete and optimal recommendations (of course
this takes the most time too).
An excerpt from "Visual Basic Developer's Guide to SQL Server", ISBN # 0-7821-2679-0
Copyright © 2000 SYBEX, Inc., Alameda, CA. www.sybex.com
2679c06.qxd 4/18/2000 2:43 PM Page 187
FIGURE 6.19:
Server and database
options in the Index
Tuning Wizard
You then select whether or not you have an existing workload file for the Index
Tuning Wizard to analyze. If you select to create the workload file, the wizard
ends and brings you into Profiler. Figure 6.20 shows this screen.
FIGURE 6.20:
Workload options in the
Index Tuning Wizard
An excerpt from "Visual Basic Developer's Guide to SQL Server", ISBN # 0-7821-2679-0
Copyright © 2000 SYBEX, Inc., Alameda, CA. www.sybex.com
2679c06.qxd 4/18/2000 2:43 PM Page 188
The next screen, as shown in Figure 6.21, allows you to specify the workload
file or table name and any advanced options. The advanced options let you limit
the number and size of the indexes that the Index Tuning Wizard recommends.
Select these options if your server has disk space limitations or if you’re analyz-
ing a particularly large database.
FIGURE 6.21:
Workload locations and
advanced options in the
Index Tuning Wizard
By default the Index Tuning Wizard analyzes all the tables in the database you
choose. The following screen, as shown in Figure 6.22, lets you specify a subset of
tables to be included in the tuning process. This can significantly reduce the time
it takes to make recommendations. If you’re only analyzing a small workload or a
few queries, you can choose to include only the pertinent tables.
An excerpt from "Visual Basic Developer's Guide to SQL Server", ISBN # 0-7821-2679-0
Copyright © 2000 SYBEX, Inc., Alameda, CA. www.sybex.com
2679c06.qxd 4/18/2000 2:43 PM Page 189
FIGURE 6.22:
Select the tables to include
in the tuning process
After the Index Tuning Wizard has done its analysis, it displays its recommen-
dations. This screen is shown in Figure 6.23 and displays all the recommended
indexes. Click the Analysis button to find out how the Index Tuning Wizard devel-
oped its recommendations. This analysis can be saved to a file and shows you the
percentage that each index was used to best run the queries in the workload.
The subsequent screen, shown in Figure 6.24, provides you with three options
for implementing its recommended indexes:
• Apply the changes immediately
• Schedule a time to implement the recommendations
• Save the index recommendations to a SQL script file
An excerpt from "Visual Basic Developer's Guide to SQL Server", ISBN # 0-7821-2679-0
Copyright © 2000 SYBEX, Inc., Alameda, CA. www.sybex.com
2679c06.qxd 4/18/2000 2:43 PM Page 190
FIGURE 6.23:
The Index Tuning Wizard’s
recommendations
FIGURE 6.24:
Options for
implementing
the index
recommendations
The Index Tuning Wizard is very helpful for identifying optimal indexes
because it considers the queries that are being run against the database. In
An excerpt from "Visual Basic Developer's Guide to SQL Server", ISBN # 0-7821-2679-0
Copyright © 2000 SYBEX, Inc., Alameda, CA. www.sybex.com
2679c06.qxd 4/18/2000 2:43 PM Page 191
addition, it considers how the query optimizer will use various indexes to most
efficiently execute a query.
WARNING Be careful when adding indexes to a database with existing tables and queries. An
index that enables the most efficient processing of one query may adversely affect
the performance of other queries and indexes.
The Index Tuning Wizard can also be used to identify any unused indexes in a
production database that already has data and indexes. The Analysis report
shows you how often indexes are used to execute your queries and also shows
you what existing indexes are going unused.
An excerpt from "Visual Basic Developer's Guide to SQL Server", ISBN # 0-7821-2679-0
Copyright © 2000 SYBEX, Inc., Alameda, CA. www.sybex.com