Opening a 200-Million-Row Table in DataGrip Without Regretting It
DataGrip's automatic result-set paging appends LIMIT/OFFSET to your queries so opening a huge table doesn't freeze your IDE. Here's how it works, how to verify it, and where it bites.
28 Aug 2025, 17:59 UTC

Someone on your team double-clicks a table in DataGrip's database explorer. It's the events table — a couple hundred million rows. Nothing explodes. The grid fills with 500 rows and a small counter in the toolbar says something like "500 of many." That calm outcome isn't luck; it's DataGrip's automatic result-set paging doing its job. Understanding how it works — and when it quietly changes your query — is the difference between casually browsing production data and freezing your IDE at 4:55 on a Friday.
The problem paging solves
A naive database client executes your SELECT and pulls every row into memory before showing you anything. On a small table that's fine. On a large one it means minutes of waiting, a multi-gigabyte heap, and a beachball while the UI thread tries to render a million-row grid. DataGrip avoids this by fetching results in pages: it retrieves a configurable chunk of rows (the default page size is 500 in recent versions), displays them, and only fetches more when you scroll or explicitly ask.
The key mechanism is that this isn't client-side truncation. When paging is active, DataGrip transparently appends LIMIT/OFFSET — or the dialect equivalent, like FETCH FIRST n ROWS ONLY — to the SQL it sends to the server. The database does the trimming, so network traffic and IDE memory stay bounded regardless of table size.
Where the controls live
Two places matter:
- Settings/Preferences → Database → Data Editor and Viewer. Here you set the default Result Set Page Size. Drop it to 50 when you're sampling unfamiliar data; raise it when you're scanning broadly. Note that setting names and locations have shifted between DataGrip releases, so verify against your installed version.
- The result-set toolbar. Each result tab has a page-size control and a "Limit Page Size" toggle. The toggle is per-result, which is handy: you can page a huge table in one tab while running a small unbounded lookup query in another.
The row counter in the toolbar is your ground truth. If it shows a page-sized number rather than the full count, paging is on and only one page has been fetched.
A worked example: verifying the LIMIT is real
Don't take the paging on faith — check the actual SQL. Open a query console on a large table and run:
SELECT * FROM events ORDER BY created_at DESC;Then open the database output log (the Output tab in the Database tool window, or enable query logging via Help → Diagnostic Tools depending on version). With paging enabled, you'll see DataGrip issued something like:
SELECT * FROM events ORDER BY created_at DESC LIMIT 500;Toggle "Limit Page Size" off in the result toolbar, re-run, and compare: no LIMIT, a much longer fetch, and — on a genuinely big table — noticeably higher IDE memory. That on/off comparison is the fastest way to build intuition for what the feature costs and saves. No special permissions are needed beyond read access to the table; the only risk is the unbounded run itself, so do that comparison on a mid-sized table, not the biggest one you have.
Sorting and filtering get pushed down — usually
A subtle, valuable behavior: when you click a column header to sort, or use the filter row in the data editor, DataGrip translates that into ORDER BY and WHERE clauses sent to the server — but only when paging is active. That means sorting a 200-million-row table costs one indexed server-side sort of a page, not a client-side sort of nothing. With paging disabled, sorting and filtering may apply only to the rows already fetched, which can silently give you a "sorted" view of a partial dataset. If a colleague reports that a filter "didn't find" a row that definitely exists, disabled paging is the first thing to check.
The trade-offs worth respecting
Order matters. Auto-added LIMIT/OFFSET without an explicit ORDER BY returns an arbitrary page. Postgres, MySQL, and friends make no ordering guarantee without the clause, so page two might overlap page one or skip rows entirely. If you're paging through data for anything beyond eyeballing, add an explicit, deterministic ORDER BY (include a unique column as a tiebreaker).
Big pages are a footgun. Setting the page size to 1,000,000 or disabling paging "just for a second" on a huge table can exhaust the IDE's heap and freeze the UI, forcing a restart. If you genuinely need the full result, don't page it into the grid at all — use the Export Data feature, which runs the query server-side and streams the complete result set to a file (CSV, JSON, SQL inserts, and more) without materializing it in the editor. Similarly, copying from a paged grid only copies fetched rows; export is the correct tool for "give me everything."
A habit worth building
Before running any ad-hoc SELECT against a production or shared database, glance at the toolbar: is the page-size limit on? Is there an ORDER BY if the page contents matter? Those two checks take a second and eliminate the most common ways a casual look at the data turns into an incident. And if you're ever unsure what DataGrip actually sent, the output log will show you — trust the wire, not the UI.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.