databrickslabs / databrickslabs/ontos
[Perf]: Push data-catalog pagination/filters into SQL (perf follow-up to #337)
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 212
- Forks
- 71
- Avg merge
- 4d 10h
- Merged PRs (30d)
- 43
Description
Background
PR #337 (data-catalog overhaul) introduced server-side pagination, faceted hierarchy filters, and full-field search. The API contract is correct, but the implementation does the filtering/paging in Python after pulling all contract + asset columns end-to-end on every request.
Reviewer flagged this in https://github.com/databrickslabs/ontos/pull/337#pullrequestreview-... — we agreed to ship #337 with the known-follow-up disclaimer and track the proper fix here.
Hot path
Every one of these endpoints, on every page click and every debounced keystroke, re-pays the full merge cost:
GET /api/data-catalog/columns→DataCatalogManager.get_all_columnsGET /api/data-catalog/columns/search→DataCatalogManager.search_columnsGET /api/data-catalog/hierarchy→DataCatalogManager.get_hierarchy_filtersGET /api/data-catalog/tables→DataCatalogManager.get_table_list
All four call _get_columns_from_contracts() + _get_columns_from_assets() + _merge_columns() and then slice in Python:
- In-memory list slice (search):
src/backend/src/controller/data_catalog_manager.pyaround L540–555 - In-memory list slice (list view):
src/backend/src/controller/data_catalog_manager.pyaround L580–585
For tenants with thousands of registered columns this is O(N) per request, multiplied by typing speed.
Proposed direction
- Push the facet filters (catalog / schema / asset_type / system / table) into the SQLAlchemy query against
assets+data_contract_schema_properties. - Use
LIMIT/OFFSET(or keyset pagination keyed on(table_full_name, column_name)) at the DB layer. - Compute
total_countvia a singleCOUNT(*)over the same filtered query, not by materialising the full set. - Move
_matches_searchpredicates into the query asILIKE/tsvectormatches. Postgrestsvectorover(column_name, description, label, table_name, contract_name, system_name, catalog_name, schema_name, business_terms_text)is probably the right shape long-term. - Keep the merge/dedup step but apply it only to the page slice, not the universe.
Constraints
- Contract columns live in
data_contract_schema_propertiesjoined viadata_contract_schema_objectsanddata_contracts. - Asset columns live as child
assetslinked byasset_relationships.relationship_type = 'hasColumn'. The hierarchy traversal (System/Catalog/Schema parents) currently happens in Python via_resolve_asset_parents— that would either need a recursive CTE or a materialised denormalised view. - Dedup key is case-insensitive on
(table_full_name, column_name)and the 'both' source flag must survive.
Done when
- A 10K-column tenant returns a page in < 200ms for any of the four endpoints under realistic filter combinations.
total_countis exact, not estimated.- No regression in the merge/dedup tests added in #337 (
src/backend/src/tests/unit/test_data_catalog_manager.py).
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start in src/backend/src/controller/data_catalog_manager.py at get_all_columns, search_columns, get_hierarchy_filters, get_table_list, and the _get_columns_from_contracts/_get_columns_from_assets/_merge_columns path. Read src/backend/src/tests/unit/test_data_catalog_manager.py and run its merge/dedup tests before tracing the SQLAlchemy models and joins. Done means all four endpoints filter, paginate, count exactly, preserve dedup behavior, and meet the stated 10K-column latency target.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- postgresql, python, sqlalchemy
- Domain
- backend-api-design, databases, performance
- Issue type
- Refactor
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100