Thanks for writing the article, and sharing your findings here. It’s not necessarily the case that EnumerableMergeJoinRule was taking 46% of the planning time, even though removing it made the planning process faster. Reminds me of that old joke [1] about the scientist who “proved” that spiders hear through their legs.
Maybe EnumerableMergeJoinRule wasn’t needed for your query, but would removing it would damage another query. In other cases, there might be two rules that create the ingredients for a third rule to fire; you could disable either rule without ill effects, but disabling both would prevent an optimal plan being generated. You get the picture. The planning process can be more like a biological system in a Petri dish than a series of well-ordered steps. I believe this kind of software system is sometimes called a “reactor”. And yes, this presents unique problems for a profiler. A couple of things I’d keep an eye on are the size of the queue of matched rules, and the number of times each rule fires. Some rules, such as those that merge projects onto projects and filters, are doing housekeeping that is necessary due to the way Calcite stores relational expressions but isn’t doing anything that seems “useful” at a high level. If you could create a test case (either a junit method or an .iq file with a single query) and log a performance bug, I think it would be useful. Someone could point an agent at it and ask the agent to “make this query plan faster without breaking any other queries”. Julian [1] https://www.reddit.com/r/Jokes/comments/12nvzi/my_dads_favourite_joke_mine_too/ > On Oct 28, 2026, at 5:26 AM, Andrey Minogin <[email protected]> wrote: > > Hi all, > > I'd like to share an article that may be of interest here, since it is > about profiling the Calcite planner: > > The flame graph was wrong by 57×. So I'm building a profiler. > https://minogin.com/the-flame-graph-was-wrong-by-57x-so-im-building-a-profiler/ > > In my workload, ConverterRule.onMatch took about half of the planning time. > A stack-sampling flame graph put EnumerableMergeJoinRule at 0.81% of > samples, while measuring per rule gave about 46% of planning time. About > twenty rules inherit onMatch without overriding it, so the stack frames > can't tell them apart, and the expensive part of each firing (transformTo > and the re-registration that follows) runs after convert returns, under the > base class frame. > > This is not a bug report: the workload had nothing sorted for merge join to > exploit, so it says nothing against the rule itself. But it may be useful > to anyone profiling planner performance with stack-based tools. > > Best regards, > > *Andrey Minogin* > Software architect > minogin.com
