Python

Mar 22, 2024

Psycopg2 vs Psycopg3 Performance Benchmark

A bar chart of psycopg3 versus psycopg2 versus psycopg3 async for the generate_series query

Posted by

Semab Tariq

The new and improved PostgreSQL adapter for Python, psycopg3, brings significant improvements compared to its predecessor, psycopg2. It introduces built-in async support, enhancing efficiency for asynchronous tasks and an improved connection pooling feature. These enhancements make the PostgreSQL database interaction experience smoother for developers.

We commented on the latest version's supercharged performance in a previous blog post about building applications using PostgreSQL and psycopg3. In this blog post, we will actually test and compare the performance of psycopg2 and psycopg3 using various benchmarks. Let’s dive into it. 

➡️
Want to learn more about how to build your application using PostgreSQL/Timescale? Be sure to check these articles—we’re taking you from data migration to monitoring your database.

> How to Migrate Your Data to Timescale (3 Ways)
> Building Python Apps With PostgreSQL and psycopg3
> Data Visualization in PostgreSQL With Apache Superset
> 5 Ways to Monitor Your PostgreSQL Database

Psycopg 3 vs. Psycopg2 Benchmark Configurations

Environment

  • Cloud Provider: AWS
  • EC2 Instance Type: t2.xlarge
  • CPU Configuration: 4 cores
  • RAM Allocation: 16 GB
  • Hard Drive Capacity: 200 GB
  • Hard Drive Performance: 3000 IOPS
  • Operating System: Ubuntu 22.04 LTS
  • Filesystem: ext4

Framework

Versions

  • PostgreSQL = 16.2
  • Psycopg2-binary = 2.9.9
  • Psycopg[binary] = 3.1.18

Test Cases and Results


pg_type

A broad query retrieving all entries from the pg_type table (approximately 613 rows), similar to an average application query, aims to evaluate overall data decoding efficiency.

image

The difference is abysmal, with psycopg3 retrieving approximately half a million rows per second while psycopg2 handles 150,000.

generate_series

A query that generates 1,000 rows containing a single integer. This benchmark is used to test the overhead of creating and returning result records.

image

Psycopg3 does it again with approximately 1.2 million rows per second, double that of psycopg2. However, the true winner is the asynchronous version, slightly surpassing the 1.2 million mark.

large_object

A query returning 100 rows, each containing a 1 KB binary blob. This benchmark is used to stress the I/O and read buffers in particular and is one of three cases in our tests where psycopg2 fared better.

image

arrays

A query returns 100 rows, each containing an array of 100 integers. This benchmark is designed to test the performance of array decoding. Even if performing only slightly better, psycopg3 async is once again the winner.

image

copyfrom

This benchmark is used to measure the performance of copying data from standard input (STDIN) into a PostgreSQL table using the COPY command with specific row data and a large number of iterations (10,000). Psycopg3 async also performed better in this benchmark.

image

batch

This benchmark assesses the efficiency of batch-inserting data into a PostgreSQL table. We conducted 10,000 iterations to monitor the performance of the batch insertion process, with psycopg2 inserting more rows per second than the latest versions.

image

oneplusone

This benchmark simply executes the query "SELECT 1+1" to measure the time it takes to perform this basic arithmetic operation. Again, psycopg2 performed better.

image

Detailed Psycopg Benchmark Data

Here’s the detailed breakdown of results, where we can compare psycopg2 versus psycopg3 versus psycopg3 async.

python-psycopg2
Geometric mean1-pg_type.json x102-generate_series.json x103-large_object.json x104-arrays.json x105-copyfrom.json x106-batch.json x107-oneplusone.json x10
Queries/sec409.39246.18626.672099.091091.8444.4413.269249.65
Rows/sec102359.51150417.57626673.62209908.72109184.26444406.7113257.489249.65
Min latency4.85ms5.4ms1.91ms0.84ms1.72ms52.76ms617.62ms0.13ms
Mean latency24.366ms40.55ms15.936ms4.755ms9.147ms224.094ms753.025ms1.075ms
Max latency149.216ms276.6ms326.68ms29.21ms111.82ms765.09ms808.67ms9.02ms
Latency variation11.976ms (49.15%)33.858ms (83.5%)25.804ms (161.93%)3.31ms (69.61%)8.706ms (95.17%)74.057ms (33.05%)24.015ms (3.19%)0.789ms (73.34%)
python-psycopg3
Geometric mean1-pg_type.json x102-generate_series.json x103-large_object.json x104-arrays.json x105-copyfrom.json x106-batch.json x107-oneplusone.json x10
Queries/sec374.57804.451250.971013.911015.2345.664.934436.81
Rows/sec93665.83491518.871250967.46101390.58101522.77456625.684932.764436.81
Min latency5.473ms2.03ms1.06ms1.94ms1.76ms64.86ms1715.61ms0.18ms
Mean latency26.527ms12.418ms7.983ms9.853ms9.839ms218.195ms1962.827ms2.246ms
Max latency80.116ms41.09ms37.2ms21.35ms34.99ms897.54ms2139.78ms9.66ms
Latency variation7.384ms (27.83%)5.155ms (41.51%)4.073ms (51.03%)2.355ms (23.9%)4.097ms (41.64%)108.724ms (49.83%)50.299ms (2.56%)1.08ms (48.09%)
python-psycopg3-async
Geometric mean1-pg_type.json x102-generate_series.json x103-large_object.json x104-arrays.json x105-copyfrom.json x106-batch.json x107-oneplusone.json x10
Queries/sec474.94749.261286.341330.11139.0647.0311.047189.77
Rows/sec118755.18457796.171286341.35133010.47113906.13470290.0511041.447189.77
Min latency9.724ms5.92ms2.7ms5.68ms3.07ms60.8ms881.92ms0.55ms
Mean latency21.022ms13.336ms7.765ms7.51ms8.771ms212.059ms905.604ms1.385ms
Max latency37.043ms14.33ms18.98ms9.94ms21.82ms829.92ms962.93ms2.03ms
Latency variation1.136ms (5.4%)0.243ms (1.82%)1.938ms (24.96%)0.143ms (1.91%)0.524ms (5.97%)84.791ms (39.98%)18.099ms (2.0%)0.045ms (3.25%)

Next Steps

If you are wondering whether to carry on using psycopg2 in your interactions with your PostgreSQL database, we hope this convinces you to upgrade. We know it’s hard to part ways with a decade-long friend, but the performance gains brought by psycopg3 will make a difference in your development—especially if you're interacting asynchronously with your database.

To learn more about leveraging PostgreSQL and Python, read the following resources:

Create a free Timescale account today to experiment and start building with Python and our supercharged PostgreSQL.

Originally posted

Feb 28, 2024

Last updated

Mar 22, 2024

Share

Subscribe to the Timescale Newsletter

By submitting you acknowledge Timescale's Privacy Policy.