Ent API: selectBy() Unique Key Prefix
Last updated
Was this helpful?
Last updated
Was this helpful?
Similar to how loadBy()
loads a single Ent by its unique key, selectBy()
call loads multiple ents by their unique key prefix.
Loads the Ents matching the predicate, considering the predicate is a list of fields from your unique key prefix.
Logically, you can load the same Ents by just select()
call, but then, while batching, it will produce a UNION ALL
clause, which is less efficient and may cause performance problems when a large number of calls are batched. In contrast, selectBy()
never produces a UNION ALL
clause, but the price we pay for it is the implication that we can only select by the unique key prefix, not by an arbitrary predicate.
All in all, you’ll rarely need to use selectBy()
in your code. It is used interally though to fetch efficiently.
Let’s actually use Inverses to illustrate, how selectBy()
works. Internally, the Inverses Ent schema looks like this:
Sometimes, when Ent Framework needs to discover the full list of microshards on the opposite end of some field edge, it internally runs the following calls in parallel:
Notice that in this example, all parallel calls use the same prefix (type: "user2topics"
), but the very last selection field varies. For such a case (which is actually pretty common), to produce the most optimal PostgreSQL execution plan, Ent Framework builds the following batched SQL query:
Unfortunately, the above query stops being optimal when the prefix differs across multiple parallel calls. Consider this example:
Assume we try to build the batched query using the same approach as above:
In this case, PostgreSQL will often times produce a suboptimal plan with "bitmap index scan" instead of "index scan". This is partially due to the fact that our DB unique index is by (type, id1, shard2)
, and we only utilize its prefix (type, id1)
.
Luckily, there is another query plan which is used by Ent Framework in such a case:
It produces an optimal query plan for the cases when prefixes differ. (BTW, it loses in the situations when the prefix is common, for which AND id1 IN(...)
clause plays better.)