Skip to content

[CALCITE-7808] Cache recently created and decorated SQL types - #5282

Open
FrankChen021 wants to merge 1 commit into
apache:mainfrom
FrankChen021:codex/cache-precision-sql-types
Open

FrankChen021 wants to merge 1 commit into
apache:mainfrom
FrankChen021:codex/cache-precision-sql-types

Conversation

@FrankChen021

@FrankChen021 FrankChen021 commented Sep 22, 2026 •

Copy link
Copy Markdown
Member

Fixes CALCITE-7808.

Why

RelDataTypeFactoryImpl canonicalizes equivalent types through a global weak interner, but the interner receives an already constructed type. Repeated requests for the same SQL type therefore create temporary BasicSqlType, charset-wrapper, and type-digest objects before canonicalization discards them.

Large literal ARRAYs frequently request the same type shape many times. In Druid's high-locality string-IN benchmark, avoiding construction on repeated requests reduced allocation by 45.74% at 100,000 literals and 44.70% at 1,000,000 literals.

What

Add two bounded front caches to each SqlTypeFactoryImpl, with one entry per SqlTypeName in each cache:

  1. The base-type cache retains the most recently requested normalized precision and default charset.
  2. The decoration cache retains the most recent source type, charset, and collation combination.

For string literals, the entries form this pipeline:

createSqlType(CHAR, n)
  -> reuse the most recent canonical CHAR(n)

createTypeWithCharsetAndCollation(..., COERCIBLE)
  -> reuse the most recent decorated CHAR(n)

A request with a different precision or decoration replaces the previous entry; this does not retain every type from CHAR(1) through CHAR(65536). Cache misses use the existing construction and canonicalization paths, and the global weak interner remains authoritative.

Verification

  • SqlTypeFactoryTest covers base-type reuse, replacement by a different precision, and decorated-type reuse with changed charset and source cases.
  • ./gradlew :core:test --tests org.apache.calcite.sql.type.SqlTypeFactoryTest :core:autostyleJavaCheck :core:checkstyleMain :core:checkstyleTest (28 completed, 0 failed)
  • Druid InPlanningBenchmark.queryStringInSqlPlanOnly with -prof gc
Druid benchmark results
String literals Allocation before Allocation after Reduction Time before Time after
100,000 1,470.31 MiB/op 797.81 MiB/op 45.74% 743.99 ms/op 585.09 ms/op
1,000,000 14.478 GiB/op 8.007 GiB/op 44.70% 7.690 s/op 6.204 s/op

Configuration: inSubQueryThreshold=2147483647, rowsPerSegment=500000, 2 forks, 2 one-second warmup iterations, and 5 one-second measurement iterations. Allocation is cumulative bytes per operation, not retained or peak heap.

The performance measurement currently comes from Druid; a Calcite-local ubenchmark is not yet included.

Scope

The benefit depends on locality. The benchmark uses ordered numeric strings, so requests of the same character length are consecutive. Fixed-length values also have high locality, while frequently alternating lengths may have a lower hit rate. These results should not be generalized to arbitrary string workloads.

Copilot AI lite review requested due to automatic review settings September 22, 2026 10:22

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@sonarqubecloud

Copy link
Copy Markdown

@FrankChen021 FrankChen021 changed the title [CALCITE-7805] Cache recently created and decorated SQL types [CALCITE-7808] Cache recently created and decorated SQL types Sep 22, 2026

@julianhyde julianhyde left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

-1 slop

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants