Docs/SQL Editor/Query history
SQL EditorHistory

Query history

Every job your BigQuery projects ran, from Querylab.io or any other tool, in one searchable tab with its cost and a button to open it again with its results. A separate per-tab panel keeps versions of the query you're editing.

header → History
Name⏷Time⏷Query⏷Duration⏷Processed⏷Billed⏷Cost⏷
1Annual Reports2026-02-14 17:04-- Annual Sales Report (FY…1.6min4.5 TB4.5 TB$28.13
2ML Pipeline2026-02-14 16:47-- ML Feature Export1.3min3.2 TB3.2 TB$20.00
3Cohort Analysis2026-02-14 16:22-- User Cohort Retention…1.1min2.8 TB2.8 TB$17.50
4Event Analysis2026-02-14 16:11SELECT DATE(event_timestamp) AS day, event_name, COUNT(*)…55.0s2.5 TB2.5 TB$15.63
5Segments2026-02-14 13:31SELECT segment, COUNT(*)…12.0s600.0 GB600.0 GB$3.75
6Maintenance2026-02-14 11:57UPDATE `acme-analytics-prod.…12.0s120.0 MB120.0 MB$0.00
‹12›501-50 of 75 rows
Rows come straight from BigQuery's job history, so the Console query you ran at lunch is here too.

Opening it

Click the clock icon in the header (tooltip History), or run Query history from the command palette. It opens as a full tab named Query History. Under the title, one line sums up what the filters show, for example 27 queries in the last 7 days · 3.77 GB billed · $0.02 · 1 failed. The refresh button next to the project reloads the list.

Where the rows come from

Three sources, switched under Data source in the ⋯ menu at the top right of the tab. The menu also holds where the SQL source runs, the auto-run limit, the Group re-runs switch, the Columns preset of the table view, and Export history.

  • SQL (the default) reads region-us.INFORMATION_SCHEMA.JOBS_BY_USER, or JOBS_BY_PROJECT with Everyone, and goes back 180 days. It’s a billed query. It’s dry-run first; over the 100 MB auto-run limit you get an approval screen with Allow and Change limit.
  • API reads jobs from every connected project, your jobs only, and goes back 30 days. It’s free. Jobs without query text (loads, copies, exports) are skipped.
  • Demo shows 75 sample queries. Playground only; SQL is unavailable there.

Mine / Everyone in the header chooses whose jobs you see. The project picker next to it applies to the SQL source. Rows load 100 at a time; Load more sits at the end of the list. When you filter by a time range and run out of rows, Look further back widens the range one step (7 days, 30 days, 90 days).

Finding a query

The search field takes free text and typed filters:

1
status:success type:SELECT cost:>1.00 date:7d

Keys: status, type, tab, cost, bytes, date, savings, query, user, project, cache, duration, rows, slots, destination, location, job. Operators >, <, >=, <=, =; byte units B…TB; date shortcuts 1h, 24h, 7d, 30d, 90d. Free text matches the SQL, referenced tables, user email, error message, destination table and labels. The field autocompletes keys as you type.

Under the search field, filter buttons cover Time range (Last 1 hour … Last 90 days, or a custom range), Status, Type, Cost (over a set amount) and, when your jobs carry labels, Labels. The table view adds Savings. Clear all filters resets them. To filter by the Querylab.io tab a query ran from, type tab: in the search. In a narrow window the buttons collapse into one Filters button that shows how many are on. In the table view, the Columns switch in the ⋯ menu narrows the grid to the cost-comparison set.

When a search matches more than the loaded pages can show, a banner offers Scan All History, which searches the rest of your history 50 matches at a time. Cancel any time. In SQL mode the search runs server-side instead, which is the faster route for anything older than a few days.

Reading a row

The default view is a list with a detail pane. Rows are grouped by day (Today, Yesterday, then the date), and each day header shows that day’s billed bytes and cost. One row is one query:

  • Title. The name of the Querylab.io tab the query ran from, when that tab is still open and you named it. Otherwise the tables it read, with a shared dataset written once (stackoverflow · posts_answers, users), Script · 2 statements for a script, or Inline data · no tables read.
  • Second line. The output columns (→ rep_band, users, answers), or the error message in red for a failed job. When the columns can’t be named, the first line of the SQL.
  • Right side. Duration, billed bytes (cached for a cache hit), cost (<$0.01 under a cent, $0 when nothing was billed) and the time. A running job shows a dash for what isn’t final yet.

Runs of the same query that differ only in literals, comments or spacing fold into one row marked 4 runs. The Group re-runs switch in the ⋯ menu turns this off.

Click a row to select it. The detail pane beside the list (below the list’s own width, a panel that slides over it) shows the status and full time, the SQL with line numbers, and a grid of facts: duration, bytes processed and billed, cost, slot time, cache use. It also lists the tables the query read (click one to open it), the other runs of a folded row with what each one changed, and the job ID (click to copy), project, location and user.

  • Open with results opens a new query tab with the SQL, and for a recent successful job brings its results along. For a running job the button reads Open and watch; for a failed or cancelled one, Open in a new tab. Double-click a row, or press Enter on it, to do the same.
  • Edit and run opens the SQL in a new tab without results, ready to change and run.
  • Copy SQL puts the SQL on the clipboard.
  • A failed job shows its error in a red box. When Querylab.io can propose a fix, such as BigQuery’s “did you mean” name or a LIMIT for a result that was too large, the fix is a button that opens the corrected query in a new tab.
  • A running job shows the elapsed time and the slot time so far, and a Cancel job button. Bytes and cost are final when it ends.

Keyboard: ↑ and ↓ move the selection, Home and End jump to the ends, Enter opens, ⌘C copies the SQL of the selected row (when no text is selected), / focuses the search and Esc leaves it.

The Table toggle next to the filters switches to a grid with sortable columns and a TOTAL row. In the grid, the chevron in the Query cell expands the full SQL, and the row icons open the query in a new tab or copy it. The grid toolbar copies the loaded rows to the clipboard. Export history in the ⋯ menu saves the rows the filters show as CSV or JSON, as a download or on the clipboard. There’s no delete and no re-run: open the query in a tab and run it.

Pot. Savings and the Res. / OD model chips are the pricing comparison applied to each job.

Seeing usage over a period

Usage statistics is a separate tab, opened from the command palette as Usage statistics: total queries, total cost, data processed and cache-hit rate for a period, with cost and bytes over time, the ten most expensive queries, cost by user, statement types, and a slot-vs-on-demand savings summary. Same My Queries / All Users switch and the same billed INFORMATION_SCHEMA query with the same approval gate; default range is the last 30 days.

Versions of the query in a tab

The clock in the results toolbar (tooltip Query History), ⇧⌘H, or the tab’s right-click menu open a different panel: the version history of this tab’s SQL.

results toolbar → Query History
Today
v8f2a · current · 14:32 · 1,204 rows · 55.0s · 2.5 TB · $15.63
v7c19 · 14:18 · valid · 2.5 TB
v61d0 · 13:51 · error · Unrecognized name: evnt_name
Yesterday
v5b77 · 17:04 · 980 rows · 41.2s · 2.4 TB · $15.00
Each dot is a version. Executed versions glow; size scales with bytes scanned.

A checkpoint is saved on every run and on any valid edit, up to 200 per tab. Filter by All / Runs / Errors; click a version for a read-only preview with an optional diff against the current or the previous version. Hover actions: Copy SQL, Open in new tab, View results (runs only, while the results table lives), Restore this version (restoring first checkpoints what you have now).

In the Playground

History opens on the Demo source with 75 sample jobs from acme-analytics-prod; queries you run in the Playground are merged in on top. API mode works; SQL mode doesn’t.