February 28, 2025

Gel 6: Query Stats and In-Place Upgrade

With Version 6 we are shipping two of the most requested improvements when it comes to running Gel in production:

  • query performance log, and

  • minimum-downtime major upgrades (a.k.a in-place upgrade)

Let's talk about those.

Slow database queries are a fact of life, and are probably the single biggest source of frustration for developers and operators. Query perf depends greatly on the data set and the workload, so many problems only manifest in production. What's worse, queries that used to work fine might suddenly become much slower as the data set grows.

Starting with Gel 6, query execution statistics are now tracked and exposed in the sys::QueryStats view.

Copy
type sys::QueryStats extending sys::ExternalObject {
    branch: sys::Branch;
    query: std::str;
    query_type: sys::QueryType;
    tag: std::str;
    calls: std::int64;
    total_exec_time: std::duration;
    min_exec_time: std::duration;
    max_exec_time: std::duration;
    mean_exec_time: std::duration;
    stddev_exec_time: std::duration;
    ...
};

A reader familiar with PostgreSQL's pg_stat_statements extension would immediately notice similarity to it. That's not coincidental: we use a fork of the pg_stat_statements extension to expose EdgeQL query statistics. Why the fork? Primarily because the original extension tracks SQL queries and in a Gel instance those are primarily the result of EdgeQL compilation and would be hard to interpret by someone looking at the stats. It also makes little sense to store megabytes of compiled SQL text in the stats file.

What we do instead is embed metadata into generated SQL as a JSON-encoded comment. The metadata naturally includes the source EdgeQL, but we also went a bit further and added the ability to tag queries:

Copy
const taggedClient = createClient().withQueryTag("myapp/myfeature")

taggedClient.query("select User { name }")

The tag is an arbitrary string, but is conventionally structured as <source>/<feature>. The CLI and Web UI will now tag queries originating there with gel/repl and gel/webrepl correspondingly. Internal queries made by the Gel server are tagged with a gel/ prefix also.

Naturally, there's a pretty UI to explore, sort and filter query stats:

Query Statistics View

In other news, you would no longer be required to perform a full dump and restore cycle to upgrade Gel 6 to a later major version. Historically, the dump route was required because there are normally significant changes to instance metadata and the Gel standard library between major versions.

In version 6 the server learned the ability to compartmentalize the internal structures and the standard library in a way that allows initializing multiple Gel versions in the same instance without touching the data. Internally, all standard functions and operators are now shims pointing to the current implementation and so switching between versions of the standard library is a very quick (and reversible!) process.

What this means is that future major Gel version upgrades would no longer involve potentially long downtime.

Make sure you didn't miss our previous release week announcements:

This wraps the feature release week, but we're not done! There's "one more thing" (or two) that we'll be announcing in the next couple of weeks.

If you have questions about Gel 6.0 or want to discuss the release with our team, please join our upcoming office hours. We'd love to hear your feedback and talk about how you're using Gel.

ShareTweet