TableCore

Database profiler

The log of slow operations, grouped by query shape. It is the fastest route from the server is busy to this query needs this index.

What it costs, before anything else

Profiling is not free, and level 2 is not free at all

  • Profiling is per database, and it is a server-side setting you are changing. It stays on until somebody turns it off.
  • Level 1 records operations slower than a threshold you set. On a busy database that can still be a lot of writes.
  • Level 2 records every operation — including the reads this panel makes — and system.profile is a small capped collection, so it rolls over quickly and it costs a write per operation.
  • The failure mode is somebody enabling profiling on production and forgetting. TableCore is arranged around that: the level you found is remembered and offered back to you, and the offer only disappears once the server confirms it has been restored.
  • sampleRate exists exactly so you can profile a busy server without paying for everything. It is exposed here rather than buried.

The current level is named before anything is proposed, and a change goes through a confirmation naming the database, the level and the threshold. Level 2 carries its own sentence about the cost, shown while you are choosing, not after you have applied it.

Everything here is per database

The profiling level, the system.profile collection and its contents belong to one database. "Profiling is off" is therefore never a statement about the deployment, and the panel treats it that way — the state comes from the result of its own call for the database you are looking at, not from something remembered about the connection.

Changing the database in the selector also clears the restore offer: the offer belongs to the database the change happened on.

Three separate permissions

Reading the level, changing it, and reading system.profile are three different capabilities, because deployments grant them differently — and a mongos answers the read and refuses the change. A refused change stands beside the level rather than replacing it.

Being refused the level read ends the questions: on a real deployment the level and system.profile need the same role, so the second command would bring the same refusal and no new information. On shared Atlas tiers neither is permitted at all.

A router has nothing to show. A mongos holds no collections and so has no system.profile of its own. That is a topological fact and is decided before anything is sent.

The grouped view

The panel opens grouped, and that is the point of it. A list of individual entries answers which operation was slow; people arrive with which query is slow, and neither Compass nor the shell answers that. The operation list stays, one click away.

  • Sorted by total time, not by the worst single execution. A query taking 40 ms run a hundred thousand times costs more than one four-second query, and sorting by the slowest execution hides exactly that case.
  • The key is the server's query hash, and where the server does not provide one, a shape read from the command: field paths and operator names with every literal removed. An $in with a thousand values is one shape, not a thousand. The panel says which of the two keys it used, because the hash is the server's binding opinion and the description is TableCore's reading.
  • Median beside mean. A shape whose mean was dragged up by one bad execution has a median near the bottom; one that is slow every time does not.
  • Several plan cache keys under one shape is the signature of a plan cache problem — the same query answered by different plans — and it is not visible anywhere else.
  • The example is one execution and is labelled as one. The worst of them, with its real values, because its plan and its numbers are what you came for. Those values belong to that operation, not to the group.
The profiler grouped by query shape, sorted by total time, with the collection scan named on the row without expanding it.

The three numbers that matter

ReadingWhy
Plan summaryA collection scan is visible without expanding the row
Documents examined vs returnedRead amplification. "400,000 to answer with twelve" says more than either number alone
Keys examined vs documents examinedWhether an index did the work, or the collection did

Zero returned is a different sentence, not a division by zero. An operation that examined 400,000 documents and returned nothing is not infinitely amplified: the panel says examined N, returned nothing. Neither number present is a third case, and also not zero.

The window the numbers cover

system.profile is capped and rolls over, and the read stops at a limit. So the panel says how many operations the totals cover and from when — and when the limit was reached, it says plainly that the profiler may hold older operations these totals do not include.

With sampleRate below 1, every number is a sample and every total derived from it is an estimate. That is written beside the numbers, not in a tooltip.

The grouped view asks for more history (500 entries) than the list (50): counting executions over the last fifty operations would answer a different question from the one the view exists for.

From a profiled operation to a query tab

This is what makes the profiler part of TableCore rather than a dashboard.

A recorded read opens as a query: find, aggregate, count and distinct are turned back into shell text the workspace parser reads, and the selection moves to the database the operation ran in, because that is the only place the query means anything. For find and aggregate there is also explain the plan, which opens the explain dialog.

Shapes the workspace does not run — insert, getMore, administrative commands — get no button. A button that opens a tab the workspace will refuse is worse than no button.

Filtering

The filter runs on the server: minimum duration, namespace (quoted and anchored, as in current operations), operation kind, and collection scans only. The panel's own reads are excluded from the list — at level 2 the list would otherwise grow by the query that produces it.

The profile is read when the panel opens and on request, never in the sampler loop. system.profile is a collection, not a counter, and the panel is here to watch the server rather than give it work.

Not yet available

Diagnostic rules — turning these measurements into named findings — are tracked work and are not available. Today the profiler shows and groups; the interpretation is yours.

A working order

  1. Set level 1 with a threshold, or level 2 with a sampleRate, for one database.
  2. Let it run under real load for as long as you need.
  3. Read the grouped view, sorted by total time.
  4. Take the top shape's example into a query tab, and explain it.
  5. Add the index. See Indexes.
  6. Restore the profiling level from the offer the panel is still showing you.