G
Guest
Hi guys,
I’m getting a really weird problem when accessing a SQL Server 2005 database
from .NET 2.0 code. I was wondering if anyone could make any suggestions as
to what is going wrong?!
Here is the problem (names and real world equivalents have been altered!):
I have a database that stores client information. There is a top level
client table (that stores all the usual stuff like name, address, etc…) and a
collection of child tables storing things like orders placed etc… The child
tables all have one-to-many relationships with the client table, based on
ClientId. There are around six child tables. Pretty standard stuff!
The database lives on a disk array (6 drives, RAID 10 configuration) and is
split into a number of files (one per processor) on each logical drive.
I have some code (fired off in a new thread) that does the following, as
part of a Windows Service. The code is run on a powerful multi-processor
server with A LOT of RAM:
* Opens a database connection.
* Opens a SqlDataReader (using a suitably configured command).
* Loops through the data reader. The data reader gets all ClientIds from the
client table, effectively allowing me to loop through all client ids. (Only
the one field is returned.)
* For each row returned by the reader, I populate a dataset with all the
information for that client. (The data set is basically an image of the
database tables, except that it only ever holds information for one client at
a time. Obviously, this is held in memory!) I fill the data set using a
number of data adapters, one for each table. Each data adapter accepts the
client id so that the right subset of data is returned.
* Once I have the complete set of client data, I serialise the data set and
plop it into another database table (tblList) (in a var-binary field), along
with the Id in another field.
Please don’t dwell on why I’m actually doing the above. As I state above,
I’ve changed the names of tables etc… to protect intellectual property. The
requirement really does make sense in the real version of the application!
The outer loop, driven by the data reader, uses the following construct:
using (SqlDataReader reader = GetReader())
{
while (Reader.Read())
{
//Data adapter code
}
}
The “//Data adapter code†section represents the bit where a data set is
filled from data adapters. Note that the using statement should ensure that
the reader is closed after use. (When I call the reader, I use the
CommandBehavior.CloseConnection option to ensure that the connection is
closed too. Although maybe I need to somehow dispose the connection as well?)
The data adapters used should manage their own connections, right?
As you can image, there is a lot of data adapter activity, but the orders of
magnitudes of rows returned is well within the capability of the data adapter
(i.e. only a few hundred rows in a table at the most). Surely SQL Server and
..NET should more than be able to handle this kind of task? It’s not exactly
out of the ordinary… is it?
Now, this is what happens when the code runs. To begin with, all is fine. I
get good speed (around 20 clients per second). Then, as time passes, the
number of clients processed per second begins to drop off, until the thing
comes to a grinding halt. There are no obvious signs that anything is going
wrong: the processor is not being stressed, and number of database
connections is normal, there is no I/O queue, the amount of memory being
consumed by the Windows Service is similar to the amount when I started it
up, etc… The slow down is not being caused by the data itself, since all of
the clients are approximately equal in size (in terms of numbers of records).
It’s also not to do with the growing size of tblList, since if I clear this
table down when the system is running slowly, the thing does not start to
speed up. I really have no idea what is causing the application to stop
working. Note that there are around 3 million clients in the database.
Has anyone seen anything like this before? If so, what were the causes? What
additional information would I need to supply in order to help you guys make
suggestions as to what is going wrong?
Thanks in advance,
Steve.
I’m getting a really weird problem when accessing a SQL Server 2005 database
from .NET 2.0 code. I was wondering if anyone could make any suggestions as
to what is going wrong?!
Here is the problem (names and real world equivalents have been altered!):
I have a database that stores client information. There is a top level
client table (that stores all the usual stuff like name, address, etc…) and a
collection of child tables storing things like orders placed etc… The child
tables all have one-to-many relationships with the client table, based on
ClientId. There are around six child tables. Pretty standard stuff!
The database lives on a disk array (6 drives, RAID 10 configuration) and is
split into a number of files (one per processor) on each logical drive.
I have some code (fired off in a new thread) that does the following, as
part of a Windows Service. The code is run on a powerful multi-processor
server with A LOT of RAM:
* Opens a database connection.
* Opens a SqlDataReader (using a suitably configured command).
* Loops through the data reader. The data reader gets all ClientIds from the
client table, effectively allowing me to loop through all client ids. (Only
the one field is returned.)
* For each row returned by the reader, I populate a dataset with all the
information for that client. (The data set is basically an image of the
database tables, except that it only ever holds information for one client at
a time. Obviously, this is held in memory!) I fill the data set using a
number of data adapters, one for each table. Each data adapter accepts the
client id so that the right subset of data is returned.
* Once I have the complete set of client data, I serialise the data set and
plop it into another database table (tblList) (in a var-binary field), along
with the Id in another field.
Please don’t dwell on why I’m actually doing the above. As I state above,
I’ve changed the names of tables etc… to protect intellectual property. The
requirement really does make sense in the real version of the application!
The outer loop, driven by the data reader, uses the following construct:
using (SqlDataReader reader = GetReader())
{
while (Reader.Read())
{
//Data adapter code
}
}
The “//Data adapter code†section represents the bit where a data set is
filled from data adapters. Note that the using statement should ensure that
the reader is closed after use. (When I call the reader, I use the
CommandBehavior.CloseConnection option to ensure that the connection is
closed too. Although maybe I need to somehow dispose the connection as well?)
The data adapters used should manage their own connections, right?
As you can image, there is a lot of data adapter activity, but the orders of
magnitudes of rows returned is well within the capability of the data adapter
(i.e. only a few hundred rows in a table at the most). Surely SQL Server and
..NET should more than be able to handle this kind of task? It’s not exactly
out of the ordinary… is it?
Now, this is what happens when the code runs. To begin with, all is fine. I
get good speed (around 20 clients per second). Then, as time passes, the
number of clients processed per second begins to drop off, until the thing
comes to a grinding halt. There are no obvious signs that anything is going
wrong: the processor is not being stressed, and number of database
connections is normal, there is no I/O queue, the amount of memory being
consumed by the Windows Service is similar to the amount when I started it
up, etc… The slow down is not being caused by the data itself, since all of
the clients are approximately equal in size (in terms of numbers of records).
It’s also not to do with the growing size of tblList, since if I clear this
table down when the system is running slowly, the thing does not start to
speed up. I really have no idea what is causing the application to stop
working. Note that there are around 3 million clients in the database.
Has anyone seen anything like this before? If so, what were the causes? What
additional information would I need to supply in order to help you guys make
suggestions as to what is going wrong?
Thanks in advance,
Steve.