How to Optimize SQL Parsing Performance¶
The three highest-impact optimizations when parsing SQL at scale with General SQL Parser are: reuse parser instances instead of constructing a new TGSqlParser per statement, split very large scripts with getrawsqlstatements() before building full parse trees, and parallelize across threads with one parser instance per thread. This guide shows each technique with verified APIs, plus how to measure where time is going with GSP's built-in phase timers.
Reuse Parser Instances¶
Constructing a TGSqlParser is cheap, but the first parse() for a vendor loads that dialect's parse tables. Keeping one instance alive per vendor amortizes that warm-up and avoids repeated allocation. Reuse is fully supported: each parse() call clears the previous error list, and assigning new sqltext replaces the input.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | |
Two rules for safe reuse:
- Consume results between calls. The statement list belongs to the parser; copy out the data you need (table names, errors, statement text) before parsing the next input.
- One vendor per instance. Keep a separate parser per
EDbVendorrather than reconfiguring — switching dialects forfeits the loaded-tables benefit.
Split Large Scripts Before Full Parsing¶
For multi-megabyte migration scripts or DDL dumps, you often don't need a full AST of everything at once. getrawsqlstatements() splits a script into individual statements without syntax checking or building parse trees — it is much faster than parse() and dramatically reduces peak memory:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | |
This "split, filter, then parse" pipeline bounds memory to one statement's AST at a time and lets you skip statements you don't care about (comments, GRANTs, huge INSERT VALUES batches) before doing full work. Batch separators like SQL Server's GO are understood by the splitter — see Handle SQL Server T-SQL.
Tokenizing without parsing¶
If you only need tokens — for search, masking, or statistics — tokenizeSqltext() is cheaper still. It fills getSourcetokenlist() (a TSourceTokenList) with classified tokens and never runs the grammar:
1 2 3 4 | |
Parallel Parsing: One Parser Per Thread¶
TGSqlParser instances are not thread-safe — never share one instance across threads. The supported pattern is one instance per thread, which scales linearly because parsing is CPU-bound with no shared state:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | |
Partition work at the file or statement level (use the splitting technique above to fan a single huge script out across workers). For one-off needs inside a parallel pipeline, the static helpers TGSqlParser.parseSubquery(vendor, sql) and TGSqlParser.parseExpression(vendor, sql) are documented thread-safe.
Measure Before Tuning¶
GSP has built-in phase timers, so you can see whether time goes to statement splitting, grammar parsing, or semantic analysis (table/column linking):
1 2 3 4 5 6 7 8 9 | |
Call resetTimeCounters() between measurement batches — the counters accumulate across parse() calls, which is convenient for measuring throughput over many statements.
Memory Notes¶
- The AST references the full token list. Holding parsed statements alive holds their source tokens too. Extract lightweight results (names, positions, strings) and let the statement objects go.
- Peak memory follows the largest single input, not the total workload — which is why splitting a huge script and parsing statement-by-statement is the main memory lever.
- Generated
INSERTdumps (millions of literal rows) are the classic memory hazard. Detect them cheaply aftergetrawsqlstatements()(statement text length is available without parsing) and handle them with the tokenizer instead of a full parse. - If you see
OutOfMemoryErroron legitimate workloads, raise the JVM heap (-Xmx) — parsing is allocation-heavy but short-lived, so generational GC handles it well.
Checklist¶
- Reuse one
TGSqlParserper vendor per thread. - Split big scripts with
getrawsqlstatements(); parse statements selectively. - Use
tokenizeSqltext()when tokens are enough. - Parallelize with thread-confined parser instances.
- Turn on
setEnableTimeLogging(true)and measure before optimizing further.
Related Pages¶
- Error Handling — per-statement validation built on the same loop
- Performance Considerations — architecture background
- Handle SQL Server T-SQL — batch (
GO) splitting specifics - Quick Start — installation and first parse