EF Core vs redb: an object graph against 54 tables and Include
A practitioner's benchmark comparing EF Core with redb Pro on the same Employee object: the EF Core side needs 54 tables, 59 foreign keys and 31 `Include` chains, while redb keeps the graph in a single class. The article argues the gap comes from how many tables must be reassembled into a business object, and walks through query-shape and index changes in recent redb releases.
Key points
- Reading one business object that expands to 54 tables and 59 foreign keys needs 31 `Include` chains in EF Core, plus `AsSplitQuery()` to avoid row multiplication.
- On 100k objects, loading one employee whole takes 62 queries and about two seconds in EF Core versus 9 queries and 131 ms in redb Pro.
- Cost scales with schema width, not row count: every independent collection adds a split query, so large graphs stay a discipline of their own.
- Reordering value indexes to "structure, value, object" takes a filtered, sorted page in PostgreSQL from 229 ms to 2 ms.
- This is the vendor benchmarking its own product; read the numbers together with the stated hardware and dataset.
A single business object is the test case: an employee record with addresses, contacts, dictionaries and references to other objects. Expanded into normal form for EF Core it becomes 54 tables and 59 foreign keys, and reading it back needs 31 `Include` chains plus `AsSplitQuery()`. On 100k objects, loading one employee whole costs 62 queries and about two seconds in EF Core, against 9 queries and 131 ms in redb Pro.
Much of the argument is about indexes. Ordered "structure, object, value", a value index cannot answer which objects hold a given value; reordering to "structure, value, object" in 4.4.0 cuts a filtered, sorted page in PostgreSQL from 229 ms to 2 ms. Note that the vendor is benchmarking its own product.
Real-world use
- Planning read costs in domain models where one record fans out into dozens of child tables, as in ERP or transportation management systems.
- Revisiting `AsSplitQuery()` decisions in an existing EF Core `DbContext` whose `Include` chains keep growing.
- Choosing index column order for key/value-shaped storage on PostgreSQL or SQL Server based on the queries actually run.
- Evaluating a flat relational copy of graph-shaped data for reporting and analytics.
Why it matters
As an EF Core relationship graph grows, read cost tracks the shape of the model rather than the volume of data, which turns `Include` design and query splitting into architecture decisions rather than query-level tweaks.