Talaria

In the request · 3 min read · Updated 2026-08-14

Slow queries and N+1

Most “the database is slow” incidents are the application asking the same question too many times — or once, too late.

Object-relational mappers made N+1 famous: load a list of orders, then lazily load each customer in a loop. Twenty orders become twenty-one queries. The database is fine. The chatty application is not. APM that cannot show that pattern will send you to tune indexes that were never the problem.

The problem

Two database failures look identical on a host dashboard and opposite on a waterfall. A 900ms SELECT with a missing index is one fat bar. An N+1 is a comb of identical short bars. Treating both as “MySQL is slow” wastes the week.

What it is

A slow query in Talaria is a database span whose duration meets a threshold (API default 200ms). The span carries OpenTelemetry attributes: db.system.name, sanitized db.query.text, db.operation.name.

N+1 detection is a heuristic applied at ingest: if the same db.query.text appears ten or more times in one trace, those spans are flagged. The waterfall shows an N+1 badge; Performance lists them under “N+1 and slow queries.” This is exact query-text matching after sanitization — not ORM-aware lazy-load analysis, and not a rewrite of your DataObject relations.

Trace

00-3a91… · 184 ms

production
  1. GET /checkout

  2. SELECT orders

  3. SELECT customer

    N+1
  4. SELECT customer

    N+1
  5. SELECT customer

    N+1
  6. POST stripe.com

Identical short DB spans under one transaction are the visual signature of N+1. One long DB span is a different bug.

What it gives a team

  • A queue of queries worth reading, ordered by duration, without a DBA workstation.
  • A badge that says “you asked this ten times” before you add a composite index.
  • Evidence you can paste into a PR: this trace, this query text, this count.

How Talaria does it

PHP records DB spans through TracingPdo / TracingPdoStatement. Silverstripe wraps MySQL when tracing is on (TracingMySQLDatabase). Redis is a separate db.system.name=redis path — it shows as a dependency peer, not this slow-query list (the list filters db_system IS NOT NULL with a duration threshold aimed at query work).

The dashboard calls SpansEndpoint.slowQueries with a default minDurationMs of 200. Project Settings can store slowQueryMs; the list you see today uses the API default unless a caller passes a different minimum.

Dart and Flutter do not auto-instrument SQL. Browser JavaScript has no application database. N+1 here is a server-side PHP/Silverstripe signal.

How to read it

  • Sort mentally: one slow statement vs many identical ones. The fix is different.
  • Open the parent waterfall before rewriting the query. Confirm the span sits on the critical path.
  • If the text is a SELECT in a loop, look for a join, prefetch, or batched ID query in your ORM — not a new index on an already-indexed primary key.

Turn it on

Enable tracing on the PHP or Silverstripe SDK. PDO and Silverstripe MySQL wrappers attach automatically when tracing is on. There is no separate “database APM” flag.

What this is not

This is not pg_stat_statements, EXPLAIN, or a host agent on the database box. It does not see queries from other apps sharing the same MySQL. It will miss N+1 that uses slightly different SQL text, and it will not flag nine repeats (the threshold is ten).

Related guides

  • Signals · 3 min

    How to read a request waterfall

    A waterfall is the trace drawn as time. The critical path is the longest chain of parent-to-child work — that is usually the fix.

  • In the request · 3 min

    External dependencies

    Every outbound call is a peer: HTTP hosts, databases, Redis, queues. Watch their error rate and p95 the same way you watch your own routes.

  • Signals · 3 min

    Transactions, traces, and spans

    A trace is one request’s path. A span is a timed unit of work. A transaction is the root span Talaria meters.

Turn tracing on

Opt into enableTracing on an official SDK, then inspect transactions next to the issues they belong to.