Measuring the Impact of Round-Trip Latency Between the App and the DB on Response Time with TiDB Cloud Starter

Measuring the Impact of Round-Trip Latency Between the App and the DB on Response Time with TiDB Cloud Starter

I measured response times while varying the round-trip latency between an app and TiDB Cloud Starter and the number of SQL statements per request. Added latency roughly equals latency times sequential round trips. Consolidating SQL cut it by 65%+, and reusing connections by 70%+.
2026.10.15

This page has been translated by machine translation. View original

Introduction

When you use a cloud DB such as TiDB Cloud, a network sits between the app and the DB. Many people probably worry that even if the DB processes queries quickly, communication latency will slow down responses.

Every time you send a SQL statement, the round-trip time between the app and the DB is added. Even if the SQL processing itself is short, if you write code that sends SQL sequentially many times within one request, the round-trip time should accumulate as many times as the number of queries.

In this article, I vary the round-trip latency between the app and TiDB Cloud Starter and the number of SQL statements executed per request, and measure how the app's response time changes.

The increase in response time was determined not by the size of the round-trip latency but by the number of sequential round trips to the DB per request. Consolidating SQL from 6 statements to 2 reduced the response time by 66.9% even under a condition with a round-trip time of about 100 ms.

What is TiDB Cloud

TiDB Cloud is a managed service for TiDB, a MySQL-compatible distributed database. Starter is a pay-as-you-go plan, and instances that meet the conditions receive a free tier.

Test environment

  • TiDB Cloud Starter (AWS Tokyo region)
  • TiDB v8.5.3
  • macOS
  • Python 3.13
  • PyMySQL 2.2.8
  • Toxiproxy 2.12.0
  • Measurement date: October 14, 2026

Intended audience

  • Developers considering adopting or placing a cloud DB
  • Those who want to know the relationship between how DB access is written and response time

References

Test method

The subject is the order history screen of an e-commerce site.

The process of returning a customer's latest 5 orders and the line items of each order is treated as one request. I implemented this process in two ways that differ in how SQL is sent.

Implementation Number of SQL statements Description
Sequential fetch 6 After fetching 5 orders, fetch the line items for each order
Batch fetch 2 After fetching 5 orders, fetch the line items for all 5 in a single query using an IN clause

Sequential fetch is the so-called N+1 style. I confirmed at every measurement that the two implementations return the same result.

Tables and data

I create orders for orders and order_items for order line items.

Each of 1,000 customers has 10 orders, and each order has 5 line items. That is 10,000 orders and 50,000 line items.

CREATE TABLE orders (
  id BIGINT PRIMARY KEY,
  customer_id INT NOT NULL,
  ordered_at DATETIME NOT NULL,
  KEY idx_customer (customer_id, ordered_at DESC)
);

CREATE TABLE order_items (
  order_id BIGINT NOT NULL,
  line_no TINYINT NOT NULL,
  product_name VARCHAR(64) NOT NULL,
  qty TINYINT NOT NULL,
  unit_price INT NOT NULL,
  PRIMARY KEY (order_id, line_no)
);

The two implementations

Sequential fetch retrieves the orders and then sends a line-item SQL statement for each order.

latency_bench.py (excerpt)
def order_page_sequential(cur, customer_id, sql_sec=None):
    """注文 5 件を取り、注文ごとに明細を取る (SQL 6 回)。"""
    sql_sec = [] if sql_sec is None else sql_sec
    orders, sec = timed(cur, ORDERS_SQL, (customer_id,))
    sql_sec.append(sec)
    page = []
    for order_id, ordered_at in orders:
        items, sec = timed(cur, ITEMS_ONE_SQL, (order_id,))
        sql_sec.append(sec)
        page.append({"id": order_id, "ordered_at": str(ordered_at), "items": [list(i[1:]) for i in items]})
    return page

Batch fetch passes the order IDs together to an IN clause and retrieves the line items in one query.

latency_bench.py (excerpt)
def order_page_batched(cur, customer_id, sql_sec=None):
    """注文 5 件を取り、明細を IN 句で 1 回で取る (SQL 2 回)。"""
    sql_sec = [] if sql_sec is None else sql_sec
    orders, sec = timed(cur, ORDERS_SQL, (customer_id,))
    sql_sec.append(sec)
    ids = [o[0] for o in orders]
    items, sec = timed(cur, ITEMS_IN_SQL.format(",".join(["%s"] * len(ids))), ids)
    sql_sec.append(sec)
    by_order = {}
    for item in items:
        by_order.setdefault(item[0], []).append(list(item[1:]))
    return [{"id": oid, "ordered_at": str(at), "items": by_order.get(oid, [])} for oid, at in orders]

How latency is added

Instead of changing the distance between the app and the DB, I placed the Toxiproxy proxy between my local Mac and TiDB Cloud and added round-trip latency artificially. Half of the latency is set on upstream and half on downstream, and the added round-trip latency has three levels: 0 ms, 20 ms, and 80 ms.

start-toxiproxy.sh
docker run -d --rm --name tidb-latency-proxy \
  -p 127.0.0.1:8474:8474 -p 127.0.0.1:13306:13306 \
  ghcr.io/shopify/toxiproxy:2.12.0
python latency_bench.py proxy

In the script, only the TCP connection destination is pointed at the proxy, and the TLS certificate and hostname are verified as those of TiDB Cloud.

Measurement procedure

All times are elapsed times measured on the client. The response time of one request is the time from the start of processing until the result of the last SQL statement is received and the result is assembled.

In the main comparison experiment, I reused a single connection, performed 3 warm-up runs at each latency, and then ran each of the two implementations 30 times. The execution order of the implementations was swapped on every run, and the order of latencies was also swapped every 10 runs. Before and after each latency, I ran SELECT 1 30 times to check the round-trip time.

In addition, I also ran an experiment that alternated 30 times each between creating a connection for every request and reusing a pre-created connection for the batch fetch process. The time to create a connection includes the TCP connection, the TLS handshake, and authentication.

run.sh
python latency_bench.py setup
python latency_bench.py bench 0,20,80 > bench.jsonl
python latency_bench.py conn 0,80 > conn.jsonl
python latency_bench.py summarize bench.jsonl conn.jsonl

Results are shown as the median of 30 runs and quartiles (the lower 25% value and the upper 25% value). The connection information is the values confirmed on the Connect screen of the TiDB Cloud console, passed via environment variables.

latency_bench.py
latency_bench.py
"""TiDB Cloud Starter で、通信遅延がアプリの 1 リクエストの応答時間に与える影響を計測する。

接続情報は環境変数 TIDB_HOST, TIDB_PORT, TIDB_USER, TIDB_PASSWORD から読む。
遅延は Toxiproxy (管理 API: TOXIPROXY_API、既定 http://127.0.0.1:8474) で加える。

    python latency_bench.py setup                # テーブル作成とデータ投入
    python latency_bench.py proxy                # Toxiproxy にプロキシ tidb を登録
    python latency_bench.py probe 0,20,80        # 接続時間と SELECT 1 の往復時間
    python latency_bench.py check 0,20,80        # 2 つの処理の結果一致と、遅延による増分の確認
    python latency_bench.py bench 0,20,80        # 本計測: 遅延 × 逐次取得・一括取得 (1 行 1 試行の JSON)
    python latency_bench.py conn 0,80            # 本計測: 接続を毎回作る場合と使い回す場合
    python latency_bench.py summarize bench.jsonl conn.jsonl  # 中央値と増分の集計
"""

import json
import os
import socket
import ssl
import statistics
import sys
import time
import urllib.request

import pymysql

DB = "latency_lab"
PROXY_NAME = "tidb"
PROXY_LISTEN = ("127.0.0.1", 13306)
API = os.environ.get("TOXIPROXY_API", "http://127.0.0.1:8474")

SETUP = [
    f"CREATE DATABASE IF NOT EXISTS {DB}",
    f"USE {DB}",
    "CREATE TABLE IF NOT EXISTS digit (n INT PRIMARY KEY)",
    "INSERT IGNORE INTO digit VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9)",
    """CREATE TABLE IF NOT EXISTS orders (
      id BIGINT PRIMARY KEY,
      customer_id INT NOT NULL,
      ordered_at DATETIME NOT NULL,
      KEY idx_customer (customer_id, ordered_at DESC)
    )""",
    """CREATE TABLE IF NOT EXISTS order_items (
      order_id BIGINT NOT NULL,
      line_no TINYINT NOT NULL,
      product_name VARCHAR(64) NOT NULL,
      qty TINYINT NOT NULL,
      unit_price INT NOT NULL,
      PRIMARY KEY (order_id, line_no)
    )""",
]

# 顧客 1,000 人 × 注文 10 件 = 注文 10,000 件、注文ごとに明細 5 件
LOAD = [
    """INSERT INTO orders
    SELECT x.id, 1 + MOD(x.id - 1, 1000),
           DATE_ADD('2026-09-01', INTERVAL x.id MINUTE)
    FROM (
      SELECT 1 + a.n + 10*b.n + 100*c.n + 1000*d.n AS id
      FROM digit a CROSS JOIN digit b CROSS JOIN digit c CROSS JOIN digit d
    ) AS x""",
    """INSERT INTO order_items
    SELECT o.id, e.n + 1, CONCAT('product-', MOD(o.id * 7 + e.n, 500)),
           1 + MOD(e.n, 3), 100 + MOD(o.id + e.n, 900)
    FROM orders AS o CROSS JOIN digit AS e WHERE e.n < 5""",
]

ORDERS_SQL = """SELECT id, ordered_at FROM orders
WHERE customer_id = %s ORDER BY ordered_at DESC LIMIT 5"""
ITEMS_ONE_SQL = """SELECT order_id, line_no, product_name, qty, unit_price
FROM order_items WHERE order_id = %s ORDER BY line_no"""
ITEMS_IN_SQL = """SELECT order_id, line_no, product_name, qty, unit_price
FROM order_items WHERE order_id IN ({}) ORDER BY order_id, line_no"""

def tls_context():
    ctx = ssl.create_default_context()
    ctx.check_hostname = True
    ctx.verify_mode = ssl.CERT_REQUIRED
    return ctx

def connect(via_proxy, database=DB):
    """TiDB に接続する。via_proxy なら TCP を Toxiproxy に向け、TLS のホスト名は TiDB のものを検証する。"""
    conn = pymysql.connect(
        host=os.environ["TIDB_HOST"],
        port=int(os.environ.get("TIDB_PORT", "4000")),
        user=os.environ["TIDB_USER"],
        password=os.environ["TIDB_PASSWORD"],
        database=database,
        ssl=tls_context(),
        autocommit=True,
        defer_connect=True,
    )
    sock = socket.create_connection(PROXY_LISTEN, timeout=30) if via_proxy else None
    conn.connect(sock=sock)
    return conn

def api(method, path, body=None):
    data = json.dumps(body).encode() if body is not None else None
    req = urllib.request.Request(API + path, data=data, method=method,
                                 headers={"Content-Type": "application/json"})
    with urllib.request.urlopen(req) as res:
        return res.read()

def set_delay(rtt_ms):
    """往復で rtt_ms だけ遅れるよう、上り・下りに半分ずつ latency を設定する。0 なら外す。"""
    for stream in ("upstream", "downstream"):
        name = f"latency_{stream}"
        try:
            api("DELETE", f"/proxies/{PROXY_NAME}/toxics/{name}")
        except urllib.error.HTTPError:
            pass
        if rtt_ms > 0:
            api("POST", f"/proxies/{PROXY_NAME}/toxics",
                {"name": name, "type": "latency", "stream": stream,
                 "attributes": {"latency": rtt_ms // 2, "jitter": 0}})

def setup():
    cur = connect(False, None).cursor()
    for sql in SETUP:
        cur.execute(sql)
    cur.execute("SELECT COUNT(*) FROM orders")
    if cur.fetchone()[0] == 0:
        for sql in LOAD:
            cur.execute(sql)
    cur.execute("SELECT (SELECT COUNT(*) FROM orders), (SELECT COUNT(*) FROM order_items)")
    print("orders, order_items:", cur.fetchone())

def proxy():
    try:
        api("DELETE", f"/proxies/{PROXY_NAME}")
    except urllib.error.HTTPError:
        pass
    api("POST", "/proxies", {"name": PROXY_NAME, "listen": "0.0.0.0:13306",
                             "upstream": f"{os.environ['TIDB_HOST']}:4000", "enabled": True})
    print(api("GET", f"/proxies/{PROXY_NAME}").decode())

def timed(cur, sql, args=None):
    start = time.perf_counter()
    cur.execute(sql, args)
    rows = cur.fetchall()
    return rows, time.perf_counter() - start

def order_page_sequential(cur, customer_id, sql_sec=None):
    """注文 5 件を取り、注文ごとに明細を取る (SQL 6 回)。"""
    sql_sec = [] if sql_sec is None else sql_sec
    orders, sec = timed(cur, ORDERS_SQL, (customer_id,))
    sql_sec.append(sec)
    page = []
    for order_id, ordered_at in orders:
        items, sec = timed(cur, ITEMS_ONE_SQL, (order_id,))
        sql_sec.append(sec)
        page.append({"id": order_id, "ordered_at": str(ordered_at), "items": [list(i[1:]) for i in items]})
    return page

def order_page_batched(cur, customer_id, sql_sec=None):
    """注文 5 件を取り、明細を IN 句で 1 回で取る (SQL 2 回)。"""
    sql_sec = [] if sql_sec is None else sql_sec
    orders, sec = timed(cur, ORDERS_SQL, (customer_id,))
    sql_sec.append(sec)
    ids = [o[0] for o in orders]
    items, sec = timed(cur, ITEMS_IN_SQL.format(",".join(["%s"] * len(ids))), ids)
    sql_sec.append(sec)
    by_order = {}
    for item in items:
        by_order.setdefault(item[0], []).append(list(item[1:]))
    return [{"id": oid, "ordered_at": str(at), "items": by_order.get(oid, [])} for oid, at in orders]

def summary(values_ms):
    q1, median, q3 = statistics.quantiles(values_ms, n=4, method="inclusive")
    return {"median": round(median, 2), "q1": round(q1, 2), "q3": round(q3, 2)}

def probe(delays, n=30):
    """接続確立の時間と SELECT 1 の往復時間を、プロキシなしと各遅延設定で測る。"""
    for label, via_proxy, delay in [("direct", False, 0)] + [(f"proxy+{d}", True, d) for d in delays]:
        if via_proxy:
            set_delay(delay)
        connect_ms, select1_ms = [], []
        for _ in range(5):
            start = time.perf_counter()
            conn = connect(via_proxy)
            connect_ms.append((time.perf_counter() - start) * 1000)
            conn.close()
        conn = connect(via_proxy)
        cur = conn.cursor()
        for _ in range(3):
            timed(cur, "SELECT 1")
        for _ in range(n):
            select1_ms.append(timed(cur, "SELECT 1")[1] * 1000)
        conn.close()
        print(json.dumps({"path": label, "connect_ms": summary(connect_ms),
                          "select1_ms": summary(select1_ms)}))
    set_delay(0)

def check(delays, n=5):
    """2 つの処理の結果一致と、各遅延設定での応答時間を数回だけ確かめる。"""
    for delay in delays:
        set_delay(delay)
        conn = connect(True)
        cur = conn.cursor()
        seq_ms, bat_ms = [], []
        for i in range(n):
            customer_id = 1 + (i * 37) % 1000
            start = time.perf_counter()
            a = order_page_sequential(cur, customer_id)
            seq_ms.append((time.perf_counter() - start) * 1000)
            start = time.perf_counter()
            b = order_page_batched(cur, customer_id)
            bat_ms.append((time.perf_counter() - start) * 1000)
            assert a == b and len(a) == 5 and all(len(o["items"]) == 5 for o in a), customer_id
        conn.close()
        print(json.dumps({"delay_ms": delay, "identical": True,
                          "sequential_ms": [round(x, 1) for x in seq_ms],
                          "batched_ms": [round(x, 1) for x in bat_ms]}))
    set_delay(0)

def select1_series(cur, n=30):
    return summary([timed(cur, "SELECT 1")[1] * 1000 for _ in range(n)])

def emit(row):
    print(json.dumps(row), flush=True)

def bench(delays, warmup=3, rounds=30, block=10):
    """遅延 × 逐次取得・一括取得。1 本の接続を使い回し、実装の実行順は周回ごと、遅延の順序はまとまりごとに入れ替える。"""
    conn = connect(True)
    cur = conn.cursor()
    pages = {"sequential": order_page_sequential, "batched": order_page_batched}
    for delay in delays:
        set_delay(delay)
        for i in range(warmup):
            for page in pages.values():
                page(cur, 1 + i)
        emit({"kind": "select1", "delay_ms": delay, "when": "before", **select1_series(cur)})
    for start in range(0, rounds, block):
        order = delays if (start // block) % 2 == 0 else list(reversed(delays))
        for delay in order:
            set_delay(delay)
            for i in range(start, start + block):
                customer_id = 1 + (i * 37) % 1000
                names = ["sequential", "batched"] if i % 2 == 0 else ["batched", "sequential"]
                for name in names:
                    sql_sec = []
                    t0 = time.perf_counter()
                    pages[name](cur, customer_id, sql_sec)
                    total = time.perf_counter() - t0
                    emit({"kind": "page", "delay_ms": delay, "round": i, "version": name,
                          "customer_id": customer_id, "total_ms": round(total * 1000, 2),
                          "sql_ms": [round(x * 1000, 2) for x in sql_sec]})
    for delay in delays:
        set_delay(delay)
        emit({"kind": "select1", "delay_ms": delay, "when": "after", **select1_series(cur)})
    set_delay(0)
    conn.close()

def conn_bench(delays, warmup=3, rounds=30):
    """一括取得の処理を、接続を毎回作る場合 (new) と使い回す場合 (reuse) で交互に実行する。"""
    for delay in delays:
        set_delay(delay)
        reuse = connect(True)
        reuse_cur = reuse.cursor()
        for i in range(warmup + rounds):
            customer_id = 1 + (i * 37) % 1000
            for mode in (["new", "reuse"] if i % 2 == 0 else ["reuse", "new"]):
                t0 = time.perf_counter()
                if mode == "new":
                    conn = connect(True)
                    connect_sec = time.perf_counter() - t0
                    order_page_batched(conn.cursor(), customer_id)
                    total = time.perf_counter() - t0
                    conn.close()
                else:
                    connect_sec = 0.0
                    order_page_batched(reuse_cur, customer_id)
                    total = time.perf_counter() - t0
                if i >= warmup:
                    emit({"kind": "conn", "delay_ms": delay, "round": i - warmup, "mode": mode,
                          "total_ms": round(total * 1000, 2), "connect_ms": round(connect_sec * 1000, 2)})
        reuse.close()
    set_delay(0)

def summarize(bench_path, conn_path):
    rows = [json.loads(line) for line in open(bench_path)]
    pages = [r for r in rows if r["kind"] == "page"]
    delays = sorted({r["delay_ms"] for r in pages})
    for version in ("sequential", "batched"):
        base = None
        for delay in delays:
            ms = summary([r["total_ms"] for r in pages if r["version"] == version and r["delay_ms"] == delay])
            base = ms["median"] if base is None else base
            print(f"{version:10} +{delay:>2} ms: median {ms['median']:7.1f} "
                  f"(q1 {ms['q1']:6.1f}, q3 {ms['q3']:6.1f})  increase {ms['median'] - base:6.1f}")
    rows = [json.loads(line) for line in open(conn_path)]
    for delay in sorted({r["delay_ms"] for r in rows}):
        for mode in ("new", "reuse"):
            target = [r for r in rows if r["delay_ms"] == delay and r["mode"] == mode]
            total = summary([r["total_ms"] for r in target])
            connect_ms = summary([r["connect_ms"] for r in target])
            print(f"conn {mode:5} +{delay:>2} ms: median {total['median']:7.1f} "
                  f"(q1 {total['q1']:6.1f}, q3 {total['q3']:6.1f})  connect {connect_ms['median']:6.1f}")

if __name__ == "__main__":
    command = sys.argv[1]
    if command == "summarize":
        summarize(sys.argv[2], sys.argv[3])
        sys.exit()
    if command in ("probe", "check", "bench", "conn"):
        {"probe": probe, "check": check, "bench": bench, "conn": conn_bench}[command](
            [int(d) for d in sys.argv[2].split(",")])
    else:
        {"setup": setup, "proxy": proxy}[command]()

Results

Checking the round-trip time

For each latency setting, I measured the round-trip time of SELECT 1. The values are the medians before and after the measurement.

{"kind": "select1", "delay_ms": 0, "when": "before", "median": 14.83, "q1": 13.86, "q3": 16.69}
{"kind": "select1", "delay_ms": 20, "when": "before", "median": 37.68, "q1": 36.4, "q3": 39.53}
{"kind": "select1", "delay_ms": 80, "when": "before", "median": 100.41, "q1": 98.3, "q3": 103.72}
(中略)
Added latency (ms) Before measurement (ms) After measurement (ms)
0 14.83 13.97
20 37.68 38.20
80 100.41 98.79

The three conditions below correspond to round-trip times of about 15 ms, about 38 ms, and about 100 ms.

Sequential fetch and batch fetch

The results of running the two implementations 30 times each for each latency setting are as follows. *The reduction rate in the table is the reduction in response time of batch fetch relative to sequential fetch.

$ python latency_bench.py summarize bench.jsonl conn.jsonl
sequential + 0 ms: median   117.2 (q1  109.5, q3  120.6)  increase    0.0
sequential +20 ms: median   254.8 (q1  249.7, q3  273.3)  increase  137.6
sequential +80 ms: median   625.7 (q1  619.5, q3  632.2)  increase  508.5
batched    + 0 ms: median    40.5 (q1   37.1, q3   42.6)  increase    0.0
batched    +20 ms: median    83.2 (q1   81.1, q3   85.9)  increase   42.7
batched    +80 ms: median   206.8 (q1  204.3, q3  208.6)  increase  166.2
(中略)
Added latency (ms) Sequential fetch (ms) Batch fetch (ms) Reduction rate (%)
0 117.2 40.5 65.4
20 254.8 83.2 67.3
80 625.7 206.8 66.9

The time per SQL statement was almost the same in the two implementations.

Batch fetch reduced response time by 65% or more at every latency.

The increase in response time from the 0 ms added-latency case is as follows.

Added latency (ms) Increase for sequential fetch (ms) Increase for batch fetch (ms)
20 137.6 42.7
80 508.5 166.2

The increase for sequential fetch was about 6.4 to 6.9 times the added latency, and the increase for batch fetch was about 2.1 times.

The increase was close to the added latency multiplied by the number of SQL statements.

How connections are created

The results of comparing the batch fetch process when creating a connection every time versus reusing one are as follows. *The reduction rate in the table is the reduction in response time when reusing a connection relative to creating one every time.

$ python latency_bench.py summarize bench.jsonl conn.jsonl
(中略)
conn new   + 0 ms: median   187.3 (q1  178.3, q3  216.5)  connect  143.8
conn reuse + 0 ms: median    38.4 (q1   35.1, q3   41.9)  connect    0.0
conn new   +80 ms: median   721.0 (q1  709.9, q3  732.9)  connect  508.8
conn reuse +80 ms: median   210.4 (q1  205.5, q3  222.3)  connect    0.0
Added latency (ms) Create every time (ms) Of which connection (ms) Reuse (ms) Reduction rate (%)
0 187.3 143.8 38.4 79.5
80 721.0 508.8 210.4 70.8

When a connection was created every time, the connection time alone took longer than the main processing of the 2 SQL statements.

With 80 ms of added latency, the connection time increased by 365.0 ms. That is an increase of more than 4 times the added latency.

Findings and discussion

From the measurement results, the increase in response time due to communication latency can be estimated as follows.

応答時間の増分 ≒ 往復時間の増分 × 1 リクエストで逐次に行う DB との往復の回数

Since the time per SQL statement was almost the same in the two implementations, it seems that most of the difference in response time in this processing comes from the number of round trips.

The process of creating a connection makes many round trips to the DB … for the TCP connection, the TLS handshake, and authentication. That is probably why the effect of a longer round-trip time was larger than for a single SQL statement. The public endpoint of TiDB Cloud Starter requires TLS connections, so in a design that recreates connections, these round trips occur for every request.

Applying the number of round trips and the round-trip time per request of the app to the estimation formula above, the appropriate measures seem to divide into the following three cases.

Situation Example Effective measure
Communication latency is unlikely to be a problem Few round trips to the DB per request and small round-trip time No action needed
Design improvements are effective N+1, SQL inside loops, a connection per request Consolidating SQL, connection pooling
Consider revisiting placement or configuration The number of round trips cannot be reduced further, and round-trip time × count exceeds the response time target Place the app in the same region as the DB, use a private endpoint (AWS PrivateLink)

For example, with a round-trip time of about 100 ms, 6 round trips to the DB alone push the response time beyond 0.6 seconds. Consolidating them into 2 brought it down to about 0.2 seconds. Improvements that reduce the number of round trips can be tried right away without changing placement, so they are worth considering before revisiting placement.

Summary

I measured response time while varying the round-trip latency between the app and TiDB Cloud Starter and the number of SQL statements per request. The increase in response time is largely determined by the product of the round-trip time and the number of sequential round trips. Consolidating SQL from 6 statements to 2 reduced response time by 65% or more, and reusing connections reduced it by 70% or more. When communication latency is a concern, it seems good to count the number of round trips to the DB per request before changing placement.


TiDB Cloudの導入・サポートはクラスメソッドにお任せください

クラスメソッドでは、TiDB Cloudの導入から運用支援まで、豊富なノウハウでお客様をサポートしています。パフォーマンスの最適化やスケーラビリティに課題を抱えている方は、ぜひご相談ください。
詳細な導入事例やサービス内容について知りたい方は、こちらからご確認いただけます。

TiDB Cloudのサポート詳細を見る

Share this article