Why is connecting to SQL Server very slow? - c#

We see that creating new connections takes about 250 milliseconds, which is much slower than expected.
From our application server to the SQL Server, we have about 1 millisecond ping-time, and we are operating inside pretty fast LAN.
Our connection string is:
Data Source=SQLServer;Initial Catalog=Database;Integrated Security=True
I have measured elapsed time around this simple statement
var conn = new SqlConnection(_connectionString);
if (conn.State == ConnectionState.Closed)
{
var sw = Stopwatch.StartNew();
await conn.OpenAsync().ConfigureAwait(false);
sw.StopAndLogIfDelay(20, _log, "Open SQL Server connection");
}
I would not expect 250 milliseconds to connect in a fast LAN. Does anyone have ideas or experience in where the problem could be?

Setting minimum connections to 50 in th sql-server connection pool solved the immidate problem.
What remains is to investigate why open db-connections takes such a long time in our organisation. I will ally with our network-team to see if we can locate the problem.

Related

Getting SQL Server timeout exception even with command timeout set to 0

I have set the command timeout to 0 as per the documentation in SQL Server. I'm indexing a large table, and still get an exception "Execution timeout expired". The timeout period elapsed prior to completion of the operation or the server is not responding. The server is responding as I watch it though the SQL Server Monitor.
Here is the pertinent code:
private void ExecuteQuery(string qStr)
{
using (SqlConnection cnx = new SqlConnection(_ConnectionString))
{
cnx.Open();
using (SqlCommand cmd = new SqlCommand(qStr, cnx))
{
cmd.CommandTimeout = 0;
cmd.ExecuteNonQuery();
}
}
}
This is the connection string
Data Source='tcp:aplace.database.windows.net,1433';Initial Catalog='SQL-Dev';User Id='user#place';Password='password';Connection Timeout=360
Why am I getting a execution timeout? I have the connection timeout set to 7200 seconds, also. I am indexing a 31 million rows table on one column.
First, connection timeout and command timeout are not the same thing. Make sure you understand the difference and are using them correctly.
Second, if this is from a web page, you also need to consider timeout values relating to the web server, etc.
Third, to verify that it is in fact a timeout issue, execute your index statement in SSMS and find out how long it takes. Since the actual indexing takes place on the SQL server no matter where it is called from, the indexing time should be roughly equal whether running from SSMS or your application.

SQL Server connection pooling on continuous running application

I've got problem with the connection pulling with continuously running program. The problem occurs when I'm doing a lot of queries (every 4 minutes 5x (querying 3 tables and saving result to one)) to DB in the Tasks. The connection pools run out of max pool connection size. The strange thing about this that I have on DB 100 of AWAITING COMMAND entries for that particular connection string / machine / user entries. My understanding is that AWAITING COMMAND means that this connection can be reused, but from some strange unknown reason to me when running commands from Tasks cannot reuse available connections and they just wait for no one, and after some time got error that I've reached the max pool connections size.
Assumptions so far:
When running commands from tasks DB interpret this as invalid to reuse available connections
Connections aren't closing, but why? Seems to closing them with using keyword. More over that is 100 AWAITING COMMANDS one the DB.
The handlers aren't garbage collected for some reason? But the 100 AC telling sth else.
UPDATE: LOCALDB OBSERVATIONS/SUMMARY:
When I'm trying to replicate this on local DB SQL Server Express this problem happen in very awkward situation. I had to add the Thread.Sleep(600000) to kind a simulate the situation. And eventually after that I was able to get the max pool error, but in this case all connections are open so its rather self explanatory.
In local -> server scenario, I don't think so that I could have 100 connections open in one time, they rather stay open for some reason. When launching this program on the localMachine -> serverDB situation I don't even need to add the Thread.Sleep(600000) in order to crash program.
All those are my assumptions based on observations. I can't think of what casing this in my continuous running service where querying the DB every 4 minutes.
PS. After my full local testing I'm confused if COMMAND AWAITING means that this connection can be reused?
UPDATE 2 Forgot to mention that my initial program can run couple of days before I eventually encounter this max pool error.
Below is the program that can generate this kind of problem:
using System;
using System.Data.SqlClient;
using System.Threading;
using System.Threading.Tasks;
namespace Pooling
{
class Program
{
private static int connectionIterations;
private static string connectionString = "Data Source=localhost;Initial Catalog=localDB;Integrated Security=True";
static void Main(string[] args)
{
try
{
Iterations();
while(true)
{
ConnectionSnowball();
}
}
catch (Exception e)
{
Console.WriteLine(e);
throw;
}
}
private static void ConnectionSnowball()
{
Parallel.For(0, connectionIterations, i =>
{
try
{
Console.WriteLine($"Connection id: {i}");
using (SqlConnection connection = new SqlConnection(connectionString))
{
SqlCommand cmd = new SqlCommand("SELECT 1 FROM test_table", connection);
connection.Open();
cmd.ExecuteNonQuery();
Thread.Sleep(600000);
}
}
catch (Exception e)
{
Console.WriteLine(e);
throw;
}
});
}
private static void Iterations()
{
connectionIterations = 200;
}
}
}
I debugged your code and found no connection leaks. You just have a connection pool overflow. I checked two possible solutions for you.
Disable pooling connections
private static string connectionString = "Data Source=localhost;Initial Catalog=localDB;Integrated Security=True;Pooling=False";
Increase connection pool
private static string connectionString = "Data Source=localhost;Initial Catalog=localDB;Integrated Security=True;Max Pool Size=200";
To test how the connections will increase and decrease before, during and after the ConnectionSnowball() call, you can use this SQL query
select count(1) from sys.dm_exec_sessions where database_id = DB_ID(N'localDB')
More details about connection string parameters
SqlConnection.ConnectionString Property
Other possible solutions is the use of SQL jobs. For this task, this may be a more appropriate solution, since a large number of connections are very resource intensive.
As there are no connection leaks in your code, Did you try Restarting IIS?

Application freeze when running long Sql queries

I have application server that connects to Sql Server database and returns query results to client applications via WCF. Most of code there is like that:
using(SqlConnection sqlConnection = GetConnectionProvider().NewConnection())
{
SqlCommand sqlCommand = new SqlCommand(data.SelectStoredProcedureName, sqlConnection);
sqlCommand.CommandType = CommandType.StoredProcedure;
sqlCommand.CommandTimeout = 600;
... add params
using (SqlDataReader sqlReader = sqlCommand.ExecuteReader())
{
... fill data
}
return serializedData;
}
in 99.99% percent of cases it works well but in some rare cases application begins to work very slowly. Average response time is 13 ms. After that freeze response time grows to 300-400 ms. Application begins to use 1 GB of memory and 100% cpu usage.
I'm not sure, but it can be related with running long sql queries. For example: during ordinary work some user runs long time running report. It can cause server freeze.
What can be a reason of that behavior? Any thounghts how I can diagnose that?

ODP.NET Connection Pooling Parameters

I am trying to configure connection pooling for my .NET application using ODP.NET version 2.111.6.20. The database is Oracle 11.1.
I am using the following connection string in my .NET 2.0 application:
Data Source=prod; User Id=FAKE_USER; Password=FAKE_PASS; Pooling=true; Min Pool Size=2; Max Pool Size=5; Connection Timeout=30;"
According to the documentation the connection pool should initialize with 2 connections and and increment up to 5 connections as needed. It should never get higher than 5 connections.
What I am seeing is the the connections are growing 2 at a time and growing up to 10 connections. I am monitoring the connections in the Oracle database by querying the v$session table so I know the connections are from that specific application originating from my application.
If anyone can help me identify what might be happening in the connection pool inside this application that might be allowing for more than the Max number of connections I would appreciate it.
Sample C# Code
Here is a sample of the code making the calls to the database:
const string connectionString = "Data Source=prod; User Id=FAKE_USER; Password=FAKE_PASS; Pooling=true; Min Pool Size=5; Max Pool Size=5; Connection Timeout=30;";
using (OracleConnection connection = new OracleConnection(connectionString)) {
connection.Open();
using (OracleCommand command = new OracleCommand("ALTER SESSION SET TIME_ZONE='UTC'", connection)) {
command.ExecuteScalar();
}
using (OracleTransaction transaction = connection.BeginTransaction()) {
const string procSql = #"BEGIN P_SERVICES.UPDATE_VERSION(:id, :version, :installDate); END;";
using (OracleCommand command = new OracleCommand(procSql, connection)) {
command.Parameters.Add(new OracleParameter("id", OracleDbType.Varchar2) { Value = id });
command.Parameters.Add(new OracleParameter("version", OracleDbType.Varchar2) { Value = version });
command.Parameters.Add(new OracleParameter("installDate", OracleDbType.TimeStamp) { Value = dateUpdated });
try {
command.ExecuteNonQuery();
} catch (OracleException oe) {
if (Log.IsErrorEnabled) {
Log.ErrorFormat("Update Error: {0}", oe.Message);
}
throw;
}
transaction.Commit();
}
}
}
I have found the reason that the Maximum connections seen in the database is increasing past the number allowed in the connection pool settings in the connection string.
The Application Pool in IIS was configured to have "Maximum number of worker processes" set different than the default of 1. What I have found is that the number of connections seen in the database can grow up to the Max Pool Size * Number of Worker Processes.
So if I have Max Pool Size of 5 and 5 Worker Processes then the total number of connections allowed is 25. So it seems that each Worker Process has it's own instance of a connection pool that is not shared across other worker processes.
You can use this query to monitor your connection counts & statuses. Using this query, I was able to confirm that the connection string settings are working, explanation below.
select COUNT(*) AS Connections
,s.username
,s.status
,s.module
,s.osuser
from V$process p
join V$session s on s.paddr = p.addr
where NOT s.UserName IS NULL
group by s.username
,s.status
,s.module
,s.osuser
I ran this with 2 pages that did a bunch of database retrievals. Here are my differing results:
Max Pool Size=5
I saw fluctuations in the count under the empty module with same username as the webserver. I'm not sure why they showed up under that bucket as well as the webserver.
Max Pool Size=1
When I restricted the pool size, I only ever saw 1 connection for the empty module, and 1 connection for the webserver, but then connections popped up under DBMS_SCHEDULER, which indicates to me that the rest of the retreivals were pending?
I think this proves that the Max Pool Size is working, but I'm not certain.
According to Tom kyte:
A connection is a physical circuit between you and the database. A connection might be
one of many types -- most popular begin DEDICATED server and SHARED server.
Zero, one or more sessions may be established over a given connection to the database
A process will be used by a session to execute statements. Sometimes
there is a one to one relationship between CONNECTION->SESSION->PROCESS (eg: a normal
dedicated server connection). Sometimes there is a one to many from connection to
sessions. A process does
not have to be dedicated to a specific connection or session however, for example when
using shared server (MTS), your SESSION will grab a process from a pool of processes in
order to execute a statement. When the call is over, that process is released back to
the pool of processes.
So running
select username from v$session where username is not null
will show current seesions (not connections)
To see the connections you may use
select username, program from v$process;
A useful book about JDBC and Session VS Connection could be found here
If you absolutely have to fix this, and are willing to get down & dirty with performance counters, this blog post might be of help. At the very least it might help narrow down a discrepency between how many connections Oracle is reporting vs. how many pooled & non-pooled connections .NET claims to have.
http://blog.ilab8.com/2011/09/02/odp-net-pooling-and-connection-request-timed-out/
These counters seem like they would be particularly useful:
NumberOfActiveConnectionPools
NumberOfActiveConnections
NumberOfFreeConnections
NumberOfInactiveConnectionPools
NumberOfNonPooledConnections
NumberOfPooledConnections
NumberOfReclaimedConnections
NumberOfStasisConnections

How long does it take to create a new database connection to SQL

Can anyone provide me with a ballpark timing (in milliseconds) for how long it takes to establish a new DB connection to SQL from C#. I.e. what is the overhead when a connection pool must create a new connection.
It depends:
time to resolve the DNS name to IP
time to open the TCP socket or the Net pipe (on top of other TCP soket): 3 IP packets usually
time to hanshake the SSL/TLS if encryption is required: ~5 roundtrips plus time to bootstrap the master key exchange if the SSL/TLS key info is not reused (ie. one RSA private key access, which is very expensive)
time to authenticate SQL password for SQL auth (2 roundtrips I believe)
time to authenticate NTLM/Kerberos for integrated auth (1 roundrip to negotiate SPNEGO, 5-6 roundtrips if Kerb ticket is missing, 1 roundtip if the ticket is present, 4-5 roundtrip if NTLM is chosen)
time to authorize the login (lookup metdata, evaluate permissions against login token)
possible time to run any login triggers
time to initiate the connection (1 roundtrip with the inital SET session stuff batch)
Some more esoteric times:
time to open auto-close databases if specified in request (may include a recovery, usualy doesn't)
time to attach database if AtachDBFile is used and db is not already attached
time to start a 'user' instance for SQL 2005 RANU. That is about 40-60 seconds.
Usually you can do some 10-15 new connections per second. If there's an issue (eg. DNS lookup problem, IPsec issued, SSL problems, Kerberos issues) it can easily go up into 10-15 seconds per conection.
By contrast an existing pooled connection only has to execute sp_resetconnection (that is one roundtrip on an existing channel), and even that can be avoided if necessary.
You could always write up some code that opens a connection to your server and time it.
Something like:
StopWatch timer = new StopWatch();
timer.Start();
for(int i=0;i<100;++i)
{
using(SqlConnection conn = new SqlConnection("SomeConnectionString;Pooling=False;"))
{
test.Open();
}
}
timer.Stop();
Console.WriteLine(test.Elapsed.Milliseconds/100);
That would get the average time to open and close 100 connections. Note, I did not run the above code
EDIT: Disabled connection pooling per Richard Szalay's comment. Otherwise, the results would be skewed
It depends on what database you are connecting to and whether it is local or across a network and the network speed if so. If everything is local, then maybe 1 or 2 milliseconds (again it depends on the DBMS). If, more realistically, it is over a LAN, it can still be pretty fast. Here is a simple example connecting to a server on a different subnet (one hop I think):
for ( int i = 0; i < 5; i++ )
{
Stopwatch timeit = new Stopwatch();
timeit.Start();
AdsConnection conn = new AdsConnection( #"Data Source = \\10.24.36.47:6262\testsys\;" );
conn.Open();
timeit.Stop();
Console.WriteLine( "Milliseconds: " + timeit.ElapsedMilliseconds.ToString() );
//conn.Close();
}
The following are the times it printed. The very first one has the cost of loading assemblies and various DLLs. The subsequent ones are only a measurement of the initialization of the new connections:
Milliseconds: 99
Milliseconds: 5
Milliseconds: 4
Milliseconds: 4
Milliseconds: 4

Categories

Resources