Repository navigation
Conversation
Selection among the plans in one tertiary plan-cache entry went by smallest plan hash, so an unconstrained plan could poison the entry and keep being handed to queries that qualified for a better plan. Replaces the hash-based StableSelectorCostModel with PlanCacheCostModel, composed from the tiebreakers introduced in #3993. It is PlanningCostModel minus every tiebreaker that reads a plan operator's match candidate, and it always costs under the default planner configuration. Fixes #4642.
|
I'm trying to model a use case:
#1: |
| @Nonnull | ||
| @Override | ||
| public RecordQueryPlannerConfiguration getConfiguration() { | ||
| return RecordQueryPlannerConfiguration.defaultPlannerConfiguration(); |
There was a problem hiding this comment.
defaultPlannerConfiguration returns builder().build() here - it is default PREFER_SCAN from record_planner_config.proto:28
however panner uses PREFER_INDEX as I understand.
Probably for configuration we need planContext.getRecordQueryPlannerConfiguration() here
There was a problem hiding this comment.
Good callout, the configuration is already part of the plan cache key, and it should be the one considered when comparing physical plans in the tertiary cache.
|
and I would try to sync somehow the rules lists in |
|
I did not get why it is |
| if (!(candidate instanceof QueryPlan.PhysicalQueryPlan)) { | ||
| return candidate; |
There was a problem hiding this comment.
Should this be returning acc? It would seem weird to return the candidate if it is not a physical query plan
There was a problem hiding this comment.
Good catch, this was supposed a final refactoring round from Claude which was over-done, incorrectly. I restored it to the previous version of the code, replacing the stable selector with the new plan-cache cost mode.
| // This currently can't be done without pulling the RecordQueryPlans out of the QueryPlan objects, | ||
| // running the cost model, and then re-associate it with the original Plan<?>, which is a bit | ||
| // costly. So, for now, just use the cost model as a comparator | ||
| stableSelectorCostModel.compare(candidateQueryPlan, bestQueryPlanSoFar) < 0) { |
There was a problem hiding this comment.
Is this supposed to be equivalent to the old code, but with the planCacheCostModel substituted for the stableSelectorCostModel, or is there another more subtle change going on?
There was a problem hiding this comment.
See my other comment, the refactoring was incorrect.
I pushed a new commit that uses the planner configuration stored in the secondary cache key to compare equivalent plans at the tertiary cache. I believe this should be now more accurate. BTW, preferring scan over index scan can be sometimes more efficient so it is not necessarily wrong.
I think we rarely add new costing rules, and so I wouldn't be worried much about divergence, they are already divergent because they work in different runtime contexts BTW, this is also ok(-ish); as we're not trying to replicate the planning cost model here, but rather come up with a good enough cost model for the plan cache that is better than a trivial hash-code comparator.
This is mostly for historical reasons; we keep the logic used exclusively by the plan generator in |
📊 Metrics Diff Analysis ReportSummary
ℹ️ About this analysisThis automated analysis compares query planner metrics between the base branch and this PR. It categorizes changes into:
The last category in particular may indicate planner regressions that should be investigated. New QueriesCount of new queries by file:
|
Selection among the plans in one tertiary plan-cache entry went by smallest plan hash, so an unconstrained plan (e.g. a full scan) could poison the entry and keep being handed to queries that qualified for a better plan.
This replaces the hash-based
StableSelectorCostModelwithPlanCacheCostModel, composed from the tiebreakers introduced in #3993. It isPlanningCostModelminus every tiebreaker that reads a plan operator's match candidate.Composing outside the
costingpackage required makingTiebreaker,TiebreakerResult,PickRightTiebreakerand the candidate-free tiebreaker factories public.Fixes #4642.