For software development and maintenance, contact me at contact@appsoftware.com or via appsoftware.com
Database Connection Pooling: How much of an overhead is it?
Tue, 28 Mar 2023 by garethbrown
To try to quantify this (using a PostrgeSQL instance), I ran an integration test under C# / XUnit. The test uses two different configuration files, one with Pooling=false
, the other with Pooling=true
.
The two connection strings were similar to below, with the only difference being the Pooling
value.
Host=localhost;User ID=postgres;Password=xxxx;Database=test_db;Port=35432;Pooling=false;
Host=localhost;User ID=postgres;Password=xxxx;Database=test_db;Port=35432;Pooling=true;
The test is using some custom utility classes, and Dapper (a light weight ORM). The query runs against a table with a small number of rows so as to get as close to testing only the difference in connection resource reuse as possible.
[Theory]
[InlineData("appsettings.DbConnectionTests.NoPooling.secret.json", 1000)]
[InlineData("appsettings.DbConnectionTests.WithPooling.secret.json", 1000)]
public async Task ConnectionSpeedTestWithPooling(string componentAppSettingsFileName, int iterations)
{
var configurationRoot = new ConfigurationBuilder()
.AddJsonFile(componentAppSettingsFileName, optional: true, reloadOnChange: true)
.Build();
var databaseConnectionInfo = new DatabaseConnectionInfo(configurationRoot);
var totalStopWatch = new Stopwatch();
totalStopWatch.Start();
for (var i = 0; i < iterations; i++)
{
using (var unitOfWork = new UnitOfWork(databaseConnectionInfo))
{
unitOfWork.ExecuteScalar("SELECT COUNT(*) FROM test_table;");
}
}
totalStopWatch.Stop();
_testOutputHelper.WriteLine($"Total Elapsed MS: {totalStopWatch.ElapsedMilliseconds}, Total MS: {totalStopWatch.ElapsedMilliseconds}, Average Per Query MS: {totalStopWatch.ElapsedMilliseconds / iterations}");
}
The output for the Pooling=false
variant:
Total Elapsed MS: 7513, Total MS: 7513, Average Per Query MS: 7
The output for the Pooling=true
variant:
Total Elapsed MS: 1072, Total MS: 1072, Average Per Query MS: 1
So the correct choice for you depends on your priority. Using connection pooling appears to significantly reduce overall load on the server by a factor of 7. On a per connection basis however, we are only looking at a difference of 6ms. In my current use case, we're trying to avoid connection starvation on an AWS RDS postgres instance that backs many containerized instances of an application, so we may opt to switch off / limit connection pooling.
Information regarding connection string parameters for PostgreSQL can be found here.
https://www.npgsql.org/doc/connection-string-parameters.html
The use of any information, code samples, or product recommendations on this Website is entirely at your own risk, and we shall not be held liable for any loss or damage, direct or indirect, arising from or in connection with the use of this Website or the information provided herein.