When diagnosing performance issues in YugabyteDB, itβs easy to focus on:
- β Query plans
- β Tablet distribution
- β RPC latency
But sometimes (or most of the time π)β¦ the database isnβt the problem at all.
π The bottleneck can be the client itself.
In this tip, weβll simulate a slow client ingesting data via COPY, and show how it surfaces in yb_active_session_history as ClientRead waits.
π‘ What does
ClientRead mean?When you see
ClientRead, YugabyteDB is
waiting on the client to send more data.β
The database is ready
β The client is slow
This is not a database performance issue… itβs a
client-side throughput or behavior problem.
π§ͺ Demo: Simulating a Slow Client with COPY
Hereβs a Python script that simulates a very slow data stream using psycopg2.
π Python Script
import psycopg2
import time
conn = psycopg2.connect("host=127.0.0.1 port=5433 dbname=yugabyte user=yugabyte")
cur = conn.cursor()
cur.execute("CREATE TABLE IF NOT EXISTS test_copy(id int, data text)")
# Custom file-like object that sends data very slowly
class SlowStream:
def __init__(self):
self.counter = 0
def read(self, size):
if self.counter >= 100:
return b'' # EOF
time.sleep(5) # simulate slow client (5 sec delay)
self.counter += 1
return f"{self.counter}\tsome data\n".encode()
def readline(self):
return self.read(0)
cur.copy_from(SlowStream(), 'test_copy', columns=('id', 'data'))
conn.commit()
π Observing the Impact in ASH
Now letβs query Active Session History:
SELECT
query_id,
wait_event_component,
wait_event,
wait_event_type,
COUNT(*)
FROM
yb_active_session_history
WHERE
sample_time >= current_timestamp - interval '20 minutes'
GROUP BY
query_id,
wait_event_component,
wait_event,
wait_event_type
ORDER BY
query_id,
wait_event_component,
wait_event_type;
π Sample Output
. query_id | wait_event_component | wait_event | wait_event_type | count
----------------------+----------------------+--------------+-----------------+-------
-7661153383196697986 | YSQL | OnCpu_Active | Cpu | 29
-500256776759016306 | YSQL | ClientRead | Client | 38
5 | YSQL | CatalogRead | RPCWait | 1
7453200712565570663 | YSQL | ClientWrite | Client | 134
π§ Whatβs Happening Here?
π Interpretation
ClientRead β Server is waiting for client input (our slow stream)
ClientWrite β Server is trying to send results to client
OnCpu_Active β Actual execution work
π In this demo, the database spends significant time idle, waiting on the client.
β‘ Why This Matters
This pattern shows up in real systems when:
- β Applications stream data too slowly (batching issues)
- β Network throughput is limited
- β Clients process data before sending next chunk
- β Misconfigured ingestion pipelines (e.g., small chunk sizes)
π The result:
- The database appears βslowβ… but itβs actually waiting.
π οΈ How to Fix It
β
Optimization Tips
- β Increase batch sizes / buffer sizes
- β Avoid per-row delays or transformations
- β Use faster ingestion methods (parallel COPY, bulk loaders)
- β Check network latency and throughput
- β Ensure client is not CPU-bound or blocked
π§Ύ TL;DR
| Signal | Meaning | Action |
|---|---|---|
| ClientRead | DB waiting for client input | β‘ Speed up ingestion / batching |
| ClientWrite | DB waiting on client to receive data | π Check network / client processing |
| OnCpu_Active | Actual query execution | π§ Tune queries if dominant |
π― Final Takeaway
When you see ClientRead, the database is not the bottleneck.
- β YugabyteDB is ready
- β The client is slow
π Focus on the application, not the database.
Have Fun!
