Repository navigation
[ESQL] Add coordinator-only caching for external source metadata - #145300
Conversation
|
Hi @costin, I've created a changelog YAML for you. |
|
Pinging @elastic/es-analytical-engine (Team:Analytics) |
🔍 Preview links for changed docs⏳ Building and deploying preview... View progress This comment will be updated with preview links when the build is complete. |
ℹ️ Important: Docs version tagging👋 Thanks for updating the docs! Just a friendly reminder that our docs are now cumulative. This means all 9.x versions are documented on the same page and published off of the main branch, instead of creating separate pages for each minor version. We use applies_to tags to mark version-specific features and changes. Expand for a quick overviewWhen to use applies_to tags:✅ At the page level to indicate which products/deployments the content applies to (mandatory) What NOT to do:❌ Don't remove or replace information that applies to an older version 🤔 Need help?
|
1f92ddd to
81dcedf
Compare
Introduce in-memory caching for schema inference and file listing results on the coordinator node, reducing repeated S3/storage API calls for external data sources. Key components: - ExternalSourceCacheService with independent schema (20% budget, 5m TTL) and listing (80% budget, 30s TTL) caches - NameId-safe SchemaCacheEntry that reconstructs fresh Attributes per query to prevent cross-query interference - Credential-isolated ListingCacheKey using MurmurHash3-128 - DictionaryFileList (~52B/file) and HiveFileList (~32B/file) compact representations, always used for multi-file sources - FileList SPI interface replacing concrete FileSet dependency - Renamed FileSet -> GenericFileList, fileSet() -> fileList() Developed with AI-assisted tooling
Consolidate GlobExpander, GenericFileList, DictionaryFileList, and HiveFileList into the datasources.glob package. All concrete FileList implementations are now package-private; consumers depend only on the FileList interface. GlobExpander is the sole public entry point for creating and compacting file lists. Extract compaction logic from HiveFileList.from/DictionaryFileList.from into a package-private FileListCompactor, eliminating the dependency between the two data classes. Both are now pure data holders. UNRESOLVED and EMPTY sentinels are inline anonymous implementations on the FileList interface.
3c0d68d to
6371cd6
Compare
…stic#145300) Introduce in-memory caching for schema inference and file listing results on the coordinator node, reducing repeated S3/storage API calls for external data sources. Schema and listing use separate caches with different TTLs, budgets, key strategies, and sharing models because they have fundamentally different invalidation characteristics. The current split is 20/80 and reflects the current first_file_wins-only schema caching, where a single schema entry (~2.5 KB for 30 columns) is cached per glob pattern while a compressed listing entry stores per-file data for potentially thousands of files (~32–52 KB for 1,000 files after compaction). Even compressed, a listing entry is 13–20× larger than a single schema entry. ## Caching details ExternalSourceCacheService manages both caches on the coordinator; total budget defaults to 0.4% of heap (esql.source.cache.size) SchemaCacheKey = anchor URI + mtime + endpoint + region + format-affecting params (delimiter, encoding, etc.) — credentials are excluded so schema is shared across users accessing the same file ListingCacheKey = scheme + bucket + glob + endpoint + region + MurmurHash3-128 of credential values — credentials are hashed (never stored) to isolate listings per user NameId-safe SchemaCacheEntry reconstructs fresh ReferenceAttribute instances per query so cached attributes never share NameIds across queries Only the first_file_wins schema resolution mode uses caching; strict and union_by_name reconciliation bypasses the schema cache since it needs all files' schemas Keeping the caches separate means a stale listing (30s) doesn't force a schema re-read (which would waste another Parquet footer fetch), and a long-lived schema entry doesn't pin a stale listing in memory. Developed with AI-assisted tooling
Summary
Introduce in-memory caching for schema inference and file listing
results on the coordinator node, reducing repeated S3/storage API
calls for external data sources.
Two-cache design
Schema and listing use separate caches with different TTLs,
budgets, key strategies, and sharing models because they have
fundamentally different invalidation characteristics:
mtimeof the anchor file embedded in the keyWhy 80/20 instead of 50/50: The split reflects the current
first_file_wins-only schema caching, where a single schema entry(~2.5 KB for 30 columns) is cached per glob pattern while a
compressed listing entry stores per-file data for potentially
thousands of files (~32–52 KB for 1,000 files after compaction).
Even compressed, a listing entry is 13–20× larger than a single
schema entry.
This ratio only holds because
strictandunion_by_namereconciliation bypasses the schema cache entirely today — it
reads all files' schemas on every query. If per-file schema caching
were added for reconciliation mode (1,000 files × 2.5 KB ≈ 2.5 MB
vs 52 KB listing), the schema side would dominate and the budget
split would need to be revisited or made adaptive.
Keeping the caches separate means a stale listing (30s) doesn't
force a schema re-read (which would waste another Parquet footer
fetch), and a long-lived schema entry doesn't pin a stale listing
in memory.
Caching details
ExternalSourceCacheServicemanages both caches on thecoordinator; total budget defaults to 0.4% of heap
(
esql.source.cache.size)SchemaCacheKey= anchor URI + mtime + endpoint + region +format-affecting params (delimiter, encoding, etc.) — credentials
are excluded so schema is shared across users accessing the same
file
ListingCacheKey= scheme + bucket + glob + endpoint + region +MurmurHash3-128 of credential values — credentials are hashed
(never stored) to isolate listings per user
NameId-safeSchemaCacheEntryreconstructs freshReferenceAttributeinstances per query so cached attributesnever share
NameIds across queriesfirst_file_winsschema resolution mode uses caching;strictandunion_by_namereconciliation bypasses the schemacache since it needs all files' schemas
File list refactoring
FileListSPI interface withUNRESOLVED/EMPTYsentinels andoptional
fileSchemaInfo()for schema reconciliationdatasources.globpackage withGlobExpanderas sole public facadeGenericFileList,DictionaryFileList(~52 B/file),HiveFileList(~32 B/file) are package-private — consumers use only
FileListFileListCompactororchestrates compaction without coupling betweenthe data classes (no HiveFileList ↔ DictionaryFileList dependency)
FileSet→GenericFileList,fileSet()→fileList()Developed with AI-assisted tooling