Sie sind auf Seite 1von 46

SYBEX Sample Chapter

Visual Basic® Developer’s Guide


to SQL Server™

by Dianne Siebold

Optimizing SQL Server Applications

Screen reproductions produced with Collage Complete.


Collage Complete is a trademark of Inner Media Inc.

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

■ 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:42 PM Page 148

148 Chapter 6 • Optimizing SQL Server Applications

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

Database Design 149

• Primary and foreign keys


• Indexes

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

150 Chapter 6 • Optimizing SQL Server Applications

The rule of thumb when creating columns is to choose the most efficient data
type depending on the data you need to store.

T A B L E 6 . 1 : SQL Server Data Types

Data Type Description Storage Visual Basic


Data Type

binary Contains up to 8,000 bytes of fixed-length n bytes as declared Variant


binary data. Fixed-length means the field
will always take up as much space as the
length you define.

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.

char Contains up to 8,000 bytes of fixed-length n bytes as declared String


string data. Use this field for data that will
always be the same length.

datetime Precise date field that stores the date and 8 bytes Date
the time accurate to milliseconds.

decimal Contains numeric data with an integer to 2–17 bytes Double


the left of the decimal point and a fractional
part to the right. This field will take a varying
number of bytes based on the scale and pre-
cision you specify. Scale is the maximum
number of digits to the right of the decimal
point and precision is the total number of
digits on both sides of the decimal point.
The maximum precision is 38.

float An approximate numeric data type for stor- 4 or 8 bytes Double


ing large floating-point numbers with preci-
sion up to 15 digits. SQL Server generally
rounds numbers up.

image Contains up to 2,147,483,647 bytes of 16-byte pointer plus String


binary data and is used for storing large as many 8 KB pages
amounts of data, like image or sound files. required to store the
Columns defined with this data type have a column data
variable length and cannot be indexed,
searched, grouped, or ordered by.

Continued on next page

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

Database Design 151

T A B L E 6 . 1 C O N T I N U E D : SQL Server Data Types

Data Type Description Storage Visual Basic


Data Type

int Stores numeric data precise to the 4 bytes Long


whole number. Can contain numbers
from –2,147,483,648 through
2,147,483,647.

money Contains decimal currency data scaled to 8 bytes Currency


4 digits of precision. Values can be from
–922,337,203,685,477.5808 through
922,337,203,685,477.5807.

nchar Contains up to 4,000 Unicode characters. n bytes (2 bytes String


Fixed-length data type stored in twice as per character) as
many bytes as characters (Unicode char- declared
acters take 2 bytes per character).

ntext Stores Unicode character data up to 16-byte pointer String


1,073,741,823 characters stored in plus as many 8
twice as many bytes as characters. KB pages
required to store
the column data

numeric Same as decimal. Double

nvarchar Contains up to 4,000 Unicode charac- n bytes (2 bytes String


ters. Variable-length data type stored in per character)
twice as many bytes as characters.

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.

smallint Stores numeric data precise to the whole 2 bytes Integer


number. Smaller than int, it can contain
numbers from –32,768 through 32,767.

smallmoney Contains decimal currency data scaled to 4 bytes Currency


4 digits of precision. Can contain values
from –214,748.3648 through
214,748.3647.

Continued on next page

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

152 Chapter 6 • Optimizing SQL Server Applications

T A B L E 6 . 1 C O N T I N U E D : SQL Server Data Types

Data Type Description Storage Visual Basic


Data Type

text Contains non-Unicode string data up to 16-byte pointer String


2,147,483,647 characters. Similar to the plus as many 8
memo data type found in other data- KB pages as are
bases, this data type stores large required to store
amounts of string data on 8 KB data the column data
pages. Columns defined with this data
type cannot be indexed, searched,
grouped, or ordered by.

timestamp A binary value that is automatically 8 bytes Variant


updated each time a record with a col-
umn of this data type is inserted or
updated. This column’s value is unique
within the database. A table can have
only one timestamp column and
although it’s unique, it’s not a good can-
didate for a primary key because of the
frequency with which it changes.

tinyint This data type can contain numbers from 1 byte Integer
0 through 255.

uniqueidentifier A string, also known as a GUID (globally 16 bytes String


unique identifier), where each character
contains a hexadecimal number. Use the
SQL Server NEWID() function to generate
a unique identifier value to populate a
variable or column of this data type.

varbinary Similar to the binary data type, it can n bytes Variant


contain up to 8,000 bytes of variable-
length binary data. Variable-length
means the field will take up as much
space as the data contained in it.

varchar Contains up to 8,000 byes of variable- n bytes String


length string data. Use this field for
columns that will store null values or
data that varies in length.

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

Database Design 153

Integer Data Types


SQL Server has four integer data types.
• bit
• int
• smallint
• tinyint

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.

Variable Length Data Types


In SQL Server 6.5, a fixed-length column that allowed null values was actually
implemented as a variable-length column. For example, a column defined as
char(7), which allowed nulls, was functionally the same as a varchar(7) column.
In SQL Server 7.0 this was changed, and any column defined as a char data type
is implemented as a fixed-length column. The same data now takes more disk
space to store. To resolve this problem, or if the data for a particular column will
vary in length, use the varchar data type.
Defining a column as varchar specifies the maximum length of the data. How-
ever, SQL Server stores only as many characters as are contained in the actual
data. If you attempt to store more than the maximum size allows, the data is trun-
cated. If the column contains less than the maximum length, no extra spaces are
stored. On the other hand, fixed-length columns will always store as much data
as the column length specifies and will pad the data value in the column with
spaces. Fixed-length columns are useful if the size of the data is not likely to vary.

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

154 Chapter 6 • Optimizing SQL Server Applications

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
)

Then add some records to the new table:


INSERT INTO Vendors (VendorName) _
VALUES(‘Acme Costumes’)
INSERT INTO Vendors (VendorName) _
VALUES(‘Acme Costumes ‘)

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.

Image and Text Data Types


The maximum row size in SQL Server is 8,060 bytes. Therefore the maximum size
of a single column is 8,000 bytes. If you want to store data that’s typically large in
size, such as images, video, sound, or more than 8,000 bytes of text data, you can
quickly reach the size limit. In this case, use the image or text data types. Each of
these data types can store up to 2,147,483,647 bytes of data. This data is not stored

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

Database Design 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

EmployeeID Notes Photo


1 Education includes BA… 0x151C2F00020000D…
2 Andrew rec’d his Ph.D… 0x151C2F00020000X…
3 Janet has a BS degree… 0x151C2F000203004…

Timestamp Data Type


The timestamp data type creates a column that contains a binary value that is
automatically updated whenever a row is inserted or updated. A timestamp col-
umn doesn’t actually contain a date and time like a datetime column; instead it
indicates the sequence of modifications that occur within that table. When SQL
Server updates a timestamp column it sets it to the database timestamp value
contained in the @@DBTS global variable.
A timestamp column is functionally the same as a binary(8) column, but you
cannot directly modify a timestamp column. If you want to track modification
dates, you must add a datetime column to the table and update it manually. A
table can have only one timestamp column and each column value is unique
within the database.
Timestamps are useful for identifying whether or not a row has changed. This
is one method for handling database concurrency issues. Let’s take a scenario
where a record with a timestamp column is retrieved, the record is modified, and
then a stored procedure is called to save the changes back to the database. The
original timestamp value can be passed into the stored procedure and the value
checked against the timestamp currently in the table to check if the record in the
database has changed since it was retrieved by the client.

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

156 Chapter 6 • Optimizing SQL Server Applications

User-Defined Data Type


User-defined data types allow you to create your own data type geared to a spe-
cific type of data. A user-defined data type is still based on one of the standard
SQL Server data types. User-defined data types can be used throughout the data-
base in which they’re defined. These data types provide consistency for specific
columns that will be used in multiple tables throughout a database. When you
create a user-defined data type you must supply three parameters:
• Name
• SQL Server base data type
• Nullability

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

Database Design 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

158 Chapter 6 • Optimizing SQL Server Applications

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.

FIGURE 6.2: Orders Table


A table that violates First
OrderID OrderDate Quantity1 OrderAmount1 Quantity2 OrderAmount2
Normal Form

108 2/9/00 28 280.00 5 10,000.00

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.

FIGURE 6.3: Orders Order Details


Tables in First Normal Form

OrderID OrderDate OrderID Quantity OrderAmount

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

Database Design 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

ShipperID ShipperName ShipperPhone

3 BDS Express 858-333-0303

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

160 Chapter 6 • Optimizing SQL Server Applications

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).

The Case For Denormalization


The first step in normalizing your database is to ensure that every table has a pri-
mary key. As you implement normalization in a database the number of tables
and columns increases, which also increases the number and complexity of joins
required to retrieve data from the database. Normalization increases the efficiency
and integrity of your database, especially for updating data. But there may be cases
where you’ll need to denormalize your tables to improve query performance.
Denormalization may be required when the number of relational joins necessary
to retrieve information causes the query time to be unacceptable. For example, if
you have a query that must perform multiple joins to return names for ID fields,
you may want to store the names in a table. Figure 6.6 shows the table joins that
would be necessary to return the order information, order details, customer name,
and shipper name from these tables.
In Figure 6.7 the database has been denormalized to make querying faster. This
is a simplified example and you probably wouldn’t denormalize these tables, but
this gives you an idea of why full normalization may not be practical. You should
consider denormalization when a query requires more than four table joins.
In the example illustrated in Figure 6.7, we saw that storing calculated values in
the database violates Third Normal Form. But if it takes an unacceptable amount
of time to derive a calculated value from the tables, it may be more efficient to store
it in a table. Let’s take the scenario of a Customers table and an Orders table related
by a Customer ID column. In this case you have a single customer with potentially
thousands of orders. To query the total of all the orders for a customer could cause
an unacceptable wait time for users of the application. In this case, it may be more
efficient to create a field in the Customers table called TotalOrderAmount and

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

Database Design 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

OrderID Quantity OrderAmount CustomerID CustomerName

108 28 280.00 Three Jewels


500
Imports
108 5 10,000.00

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

OrderID Quantity OrderAmount

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

162 Chapter 6 • Optimizing SQL Server Applications

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.

Selecting a Primary Key


If a good candidate for a primary key doesn’t exist in a table, you can create one
by defining a column of data type int and setting the identity attribute. 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 163

Database Design 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

index_name index_description index_keys


---------- ------------------------ ----------
PK_Orders clustered, unique, primary key OrderID
located on PRIMARY
CustomerID nonclustered located on PRIMARY CustomerID
CustomersOrders nonclustered located on PRIMARY CustomerID
EmployeeID nonclustered located on PRIMARY EmployeeID

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

164 Chapter 6 • Optimizing SQL Server Applications

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.

FIGURE 6.8: Orders Customers


The foreign key relationship
between Orders and OrderID CustomerID OrderDate CustomerID CustomerName
Customers tables
Three Jewels
108 500 2/9/00 500
Imports

Foreign Key Column Primary Key Column

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

Database Design 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] ‘

There is a small performance hit with check constraints when inserting or


updating data. However, it’s minimal because the constraint checks only a single
column value against the limited logic of its constraint(s). In contrast, foreign
keys must check the column value against all the column values in another table.
SQL Server lets you add multiple check constraints on a single column. Just
make sure that they don’t conflict with each other. For example, if you create a
constraint that specifies the NumberCol > 2 and another constraint that says
NumberCol < 2 you’ll never be able to add a record. In addition, your default

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

166 Chapter 6 • Optimizing SQL Server Applications

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

Indexes generally improve performance on data retrieval operations. How-


ever, the cost for this improvement is lesser performance on data modifications.
The needs of your application should be considered when selecting indexes. For
example, if part of an application does only data retrieval, it may be a good idea
to implement more indexes on your tables. For highly transactional applications
that perform a large volume of record updates, deletes, and inserts, just a few
indexes might be needed.

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

168 Chapter 6 • Optimizing SQL Server Applications

Creating a Trace Definition


Creating a trace definition can seem overwhelming, but there are really just a few
steps. The trace definition specifies what type of events you want to monitor,
what information you want to display in the trace, and how you want to filter the
trace data. Here I’ll take you step-by-step through the process of manually creat-
ing a trace that monitors the connection status and SQL activity for a single user.
1. In Profiler, select File ➢ New ➢ Trace from the menu. The Trace Properties
dialog appears, as shown in Figure 6.9.

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

170 Chapter 6 • Optimizing SQL Server Applications

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

troubleshoot the communication between a particular application and


server. If you don’t set any filters, all events will be displayed, which can
create an enormous trace file if you have a lot of busy users. To create a
filter with more than one value, use a semicolon (;) to separate the values.

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

172 Chapter 6 • Optimizing SQL Server Applications

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.

Cursors Event Category


With the event classes in this category, you can determine when a cursor is
opened or closed and what type it is (see Table 6.2).

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

T A B L E 6 . 2 : Cursors Event Classes

Event Class Description

CursorClose A previously opened cursor is closed.

CursorExecute A cursor that has been prepared is executed.

CursorImplicitConversion A cursor is converted from one type to another.

CursorOpen A cursor is opened.

CursorPrepare A cursor is prepared for execution.

CursorRecompile An open cursor is recompiled either directly or as the result of a schema


change.

CursorUnprepare A prepared cursor is deleted.

Errors and Warnings Event Category


These events enable the monitoring of errors and warnings raised by SQL Server
(see Table 6.3).

T A B L E 6 . 3 : Errors and Warnings Event Classes

Event Class Description

ErrorLog SQL Server has logged errors in the error log.

EventLog Windows 2000/NT has logged events in the application log.

Exception An exception has occurred.

Execution Warnings Warnings have occurred during the execution of a stored procedure or
SQL statement.

Hash Warning A warning has occurred during a hash operation.

Missing Column Statistics Column statistics are unavailable to a SQL query.

Missing Join Predicate The SQL query currently being executed is missing a join predicate.

OLEDB Errors An OLE DB error occurred.

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

174 Chapter 6 • Optimizing SQL Server Applications

Locks Event Category


The events listed in Table 6.4 monitor lock activity.

T A B L E 6 . 4 : Locks Event Classes

Event Class Description

Lock:Acquired A lock has been placed on a row, page, extent, table, or database.

Lock:Cancel A lock on a resource has been canceled.

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:Deadlock Chain The events leading to a deadlock.

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.

Misc Event Category


Event classes listed in Table 6.5 monitor miscellaneous events.

T A B L E 6 . 5 : Miscellaneous Event Classes

Event Class Description

Attention An attention event such as a broken connection has occurred.

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.

Execution Plan An execution plan is being displayed.

LoginFailed A login attempt has failed.

Prepare SQL A SQL statement has been prepared for execution.

Continued on next page

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

T A B L E 6 . 5 C O N T I N U E D : Miscellaneous Event Classes

Event Class Description

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.

Unprepare SQL A SQL statement has been deleted.

Objects Event Category


The events in Table 6.6 allow you to monitor activity for SQL Server objects such
as a database, table, index view, or stored procedure. Because objects are fre-
quently referenced in SQL Server, monitoring these events can create large trace
files or tables. For example, just connecting to SQL Server can produce hundreds
of object events and corresponding entries in a trace file.

T A B L E 6 . 6 : Objects Event Classes

Event Class Description

Object:Closed An object has been closed.

Object:Created An object has been created.

Object:Deleted An object has been deleted.

Object:Opened An object has been opened.

Scans Event Category


The events listed in Table 6.7 enable monitoring of table scans and index scans
when a query is executed. The type of scan can be identified by the class’s sub
events.

T A B L E 6 . 7 : Scans Event Classes

Event Class Description

Scan:Started A table or index scan has started.

Scan:Stopped A table or index scan has halted.


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 176

176 Chapter 6 • Optimizing SQL Server Applications

Each of these events has an event sub class that’s used to identify what type of
scan has occurred (see Table 6.8).

T A B L E 6 . 8 : Scans Event Sub Classes

Sub Event Scan Description

1 Normal

2 First

4 Back

8 Unordered

16 No Data

32 Reserved

64 Exlatch

128 Index supplied

256 Marker

Sessions Event Category


The Sessions events monitor server connection activity (see Table 6.9).

T A B L E 6 . 9 : Sessions Event Classes

Event Class Description

Connect A user has connected to the server.

Disconnect A user has disconnected from the server.

ExistingConnection Activity by users that were connected to the server before the trace was started
occurred.

SQL Operators Event Category


The SQL Operators event is raised whenever a SELECT, INSERT, UPDATE, or
DELETE operation occurs (see Table 6.10). Remember that these events appear in
Profiler when one of these statements is executed whether or not it’s successful. For

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.

T A B L E 6 . 1 0 : SQL Operators Event Classes

Event Class Description

SELECT A SQL SELECT statement has been executed.

INSERT A SQL INSERT statement has been executed.

UPDATE A SQL UPDATE statement has been executed.

DELETE A SQL DELETE statement has been executed.

Stored Procedures Event Category


The events listed in Table 6.11 are used to monitor stored procedure activity. Mon-
itoring these events can be extremely handy for testing and debugging if you’re
having problems calling stored procedures from within Visual Basic.

T A B L E 6 . 1 1 : Stored Procedures Event Classes

Event Class Description

SP:CacheHit A stored procedure was located in the cache.

SP:CacheInsert A stored procedure has been inserted into the cache.

SP:CacheMiss A stored procedure was not found in the cache after its attempted execution.

SP:CacheRemove A stored procedure has been removed from the cache.

SP:Completed The execution of a stored procedure has been completed.

SP:ExecContextHit The execution context for a stored procedure that executed was found in the cache.

SP:Recompile A stored procedure has been recompiled.

SP:Starting The execution of a stored procedure is starting.

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

178 Chapter 6 • Optimizing SQL Server Applications

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.

Transactions Event Category


Transactions events let you monitor SQL Server transactions. These events pro-
vide the transaction ID, the type of transaction (COMMIT or ROLLBACK), and
whether or not the transaction was logged by SQL Server (see Table 6.12).

T A B L E 6 . 1 2 : Transactions Event Classes

Event Class Description

DTCTransaction A transaction that’s managed by the DTC (an MTS transaction for example) has
occurred.

SQLTransaction A transaction has occurred as the result of a BEGIN TRANSACTION, COMMIT


TRANSACTION, SAVE TRANSACTION, or ROLLBACK TRANSACTION command.

TransactionLog A transaction has been written to the transaction log.

TSQL Event Category


TSQL events are used to monitor the execution of T-SQL statements (see Table 6.13).

T A B L E 6 . 1 3 : TSQL Event Classes

Event Class Description

RPC:Completed Commands sent to SQL Server via RPC have completed.

RPC:Starting Commands sent to SQL Server via RPC have started.

SQL:BatchCompleted Batch T-SQL commands have been completed.

SQL:BatchStarting Batch T-SQL commands have started.

SQL:StmtCompleted T-SQL statement execution has completed.

SQL:StmtStarting T-SQL statement execution has started.

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.

User Configurable Event Category


You can define up to ten user-defined events that allow you to trace activities that
are not included in the existing event categories. You are responsible for raising
these events and they are generated by calling sp_trace_generate_event and
providing an event class number that is not already used by an existing SQL
Server event class.

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

180 Chapter 6 • Optimizing SQL Server Applications

Default Trace Definitions


Profiler comes with six sample traces that you can run right away. If you’re unfa-
miliar with using Profiler, these definitions are a good place to start.
Sample 1—TSQL This trace captures basic information from the Sessions
and TSQL event categories. This trace is particularly useful for identifying
exactly what commands SQL Server is processing. If you’re using ADO in
Visual Basic, once you call the Execute method you have very little infor-
mation on the execution of a command except for possibly a return value.
With this sample trace, you can find out the commands and parameters
that SQL Server is actually processing.
Sample 2—TSQL (grouped) This trace monitors some of the events in
the Sessions and TSQL event categories just like the previous trace. But
this definition groups the trace results by Application Name, NT User
Name, SQL User Name, and Connection ID.
Sample 3—Stored Procedure Counts This trace simply monitors each
time a stored procedure is called. This information can be used to find out
what stored procedures are most often called.
Sample 4—TSQL + Stored Procedure Steps This trace monitors all
stored procedure calls and T-SQL statements. This trace is useful for inves-
tigating what stored procedures or SQL statements are actually being exe-
cuted on SQL Server when calls are made through ADO objects. You can
also use this trace to follow the activity in complex stored procedures if, for
example, you have a chain of stored procedures that are called based on
certain logic. You can identify any parameter values that SQL Server is
receiving from the client application as well as the calling chain of nested
stored procedures.
Sample 5—TSQL by duration This trace monitors the completion of T-
SQL commands on a particular server grouped by event class and dura-
tion. The results from this trace can be used to identify long-running
queries and performance bottlenecks on the server.
Sample 6—TSQL for Replay This trace monitors Cursor, Miscellaneous,
TSQL, and Sessions events for replay. You can capture this trace session to
a file or table for replay at another time. This is quite an interesting feature
because it allows you to capture the SQL Server events and then replay
them on another server if you wish. This is handy for identifying the source
of a problem; for example, if a sequence of events on your production

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

Query Analyzer 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

Query Analyzer is an indispensable tool for interactively writing and executing


T-SQL. But the ability to see a query’s execution plan graphically makes it the per-
fect tool for optimizing your T-SQL code. Before you can tune your queries you
must know how SQL Server is going to process them. Query Analyzer shows you
the proposed execution plan for a query that you can analyze to determine
whether adding an index or perhaps modifying the query syntax will improve
performance.
The execution plan in Query Analyzer is essentially a graphical representation
of the SET SHOWPLAN_ALL statement. To view the estimated execution plan
for a query, enter the query in the code pane and select Query ➢ Show Execution
Plan from the menu or click its toolbar button. The execution plan is displayed on
a tab below the code pane. The execution plan for the Employee Sales By Country
stored procedure in the Northwind database is shown in Figure 6.14.
As you can see, Query Analyzer uses icons to represent each of the steps that the
query optimizer uses to execute the query in the most efficient manner. Each step
in the plan is represented by a single icon along with the cost as a percentage of
the total execution time. For example, in the above query plan the index seek, clus-
tered index scan, and table scan are the most time and resource consuming steps
when executing this query. Hover over each step in the execution plan and a tool
tip appears with additional information about that step, as shown in Figure 6.15.

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

182 Chapter 6 • Optimizing SQL Server Applications

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

Query Analyzer 183

The information displayed in the tool tip includes:


Physical Operation The actual operation that takes place in that step
such as a clustered index scan or table scan. Any problems that would
cause the query optimizer to be less efficient are shown at the top of the
tool tip. For example, if column statistics are missing on a column, you’ll
see a warning in red and a suggested course of action. Right-clicking a step
gives you the option to modify indexes, modify statistics, or create missing
statistics.
Logical Operation The corresponding logical operation for the physical
operation.
Estimated Row Count The number of rows returned by this step.
Estimated Row Size The approximate size of each row returned by
this step.
I/O Cost The I/O required by the server engine to perform this step.
CPU Cost The CPU activity required for this step.
Number of Executes The number of times this step must be performed.
Cost The cost of this step to the query optimizer. This is a percentage of
the total query cost and this figure should be as low as possible.
SubTree Cost The cost of this step and any preceding steps.
Argument The argument associated with this step. For example, if this
step scans a clustered index, the index name appears here.

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

184 Chapter 6 • Optimizing SQL Server Applications

FIGURE 6.16:
Query execution plan when
the Employees table has no
primary key index

Because there’s no clustered index on a column that is part of a join operation,


SQL Server must perform a table scan. If you add a non-clustered primary key
index on the EmployeeID column, the query optimizer can use this index to per-
form an index seek, as shown in Figure 6.17. This operation requires only a 6%
Cost, as opposed to a table scan, which requires a 24% Cost. The Row Count goes
from 9 with no index to 1 after adding the index to the table. The I/O Cost and
CPU Cost are correspondingly reduced as well.

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

Index Tuning Wizard 185

FIGURE 6.17:
Query execution plan for
the Employees table with a
primary key index

Index Tuning Wizard


SQL Server’s query optimizer creates the most efficient plan for executing queries
regardless of whether your tables have any indexes on them. However, the appro-
priate indexes can make your queries and updates much more efficient. SQL Server
has a few tools to help you create indexes. The first of these tools is the Index Ana-
lyzer. This utility recommends table indexes based on queries or stored proce-
dures that you identify.
The Index Analyzer is available from inside the Query Analyzer by selecting
Query ➢ Perform Index Analysis from the menu. The Index Analyzer uses the
queries in the code pane and displays suggested indexes, as shown in Figure 6.18.
This tool has limited functionality and you only have the options to create the rec-
ommended indexes or exit. For a more comprehensive analysis of indexes with
more implementation options, use 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 186

186 Chapter 6 • Optimizing SQL Server Applications

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

Index Tuning Wizard 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

188 Chapter 6 • Optimizing SQL Server Applications

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

Index Tuning Wizard 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

190 Chapter 6 • Optimizing SQL Server Applications

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

Index Tuning Wizard 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

Das könnte Ihnen auch gefallen