Uploaded image for project: 'Calcite'
  1. Calcite
  2. CALCITE-6930

Implementing JoinConditionOrExpansionRule

    XMLWordPrintableJSON

Details

    • New Feature
    • Status: Closed
    • Major
    • Resolution: Fixed
    • None
    • 1.40.0
    • None

    Description

      JoinConditionOrExpansionRule transforms a join with OR conditions into a UNION ALL of multiple joins.

      For example, the SQL:

      SELECT * FROM emp JOIN dept 
      ON emp.deptno = dept.deptno OR emp.deptno = dept.mgr 

      Will be transformed into:

      SELECT * FROM emp JOIN dept ON emp.deptno = dept.deptno
      UNION ALL 
      SELECT * FROM emp JOIN dept ON emp.deptno = dept.mgr 

      The original plan:

      LogicalJoin(condition=[OR(=(deptno, deptno), =(deptno, mgr))])
        LogicalTableScan(table=emp)
          LogicalTableScan(table=dept) 

      Is transformed to:

      LogicalUnion(all=[true])
        LogicalJoin(condition=[=(deptno, deptno)])
         LogicalTableScan(table=emp)
         LogicalTableScan(table=dept)
        LogicalJoin(condition=[=(deptno, mgr)])
        LogicalTableScan(table=emp)
        LogicalTableScan(table=dept) 

      Benefits:

      1. Each individual join can use hash-join algorithm, which is more efficient than nested-loop joins required for OR conditions.
      2. Each join branch can independently choose its optimal join implementation.
      3. The joins can be executed in parallel.
      4. Individual joins may be able to use indexes that would not be usable with OR conditions.

      The rule only fires when:

      1. The OR condition contains only simple equi-join conditions (comparing columns between left and right inputs).

      Limitations and considerations:

      1. May not improve performance if individual joins produce large results that need to be union-ed.
      2. Multiple hash tables may cause memory pressure.
      3. The optimizer should consider statistics and cost estimates when applying this rule.

       

      supplement:

      1. The inner join will perform the conversion as described above.
      2. The outer join will perform the conversion more complexly.

             left join = inner join + anti join

       

      Project[*]
      └── Join[OR(t1.id=t2.id, t1.age=t2.age), left]
          ├── TableScan[t1]
          └── TableScan[t2]
      
      to
      
      Project[*]
      └── UnionAll
          ├── Join[t1.id=t2.id, inner]                    
          │   ├── TableScan[t1]
          │   └── TableScan[t2]
          ├── Join[t1.age=t2.age AND t1.id≠t2.id, inner]  
          │   ├── TableScan[t1]
          │   └── TableScan[t2]
          └── Project[t1-side cols + NULLs]                
              └── Join[t1.id=t2.id, anti]                 
                  ├── Join[t1.age=t2.age, anti]           
                  │   ├── TableScan[t1]
                  │   └── TableScan[t2]
                  └── TableScan[t2] 

       

              full join = inner join + anti join + right anti join

      Project[*]
      └── Join[OR(t1.id=t2.id, t1.age=t2.age), full]
          ├── TableScan[t1]
          └── TableScan[t2]
      
      to
      
      Project[*]
      └── UnionAll
          ├── Join[t1.id=t2.id, inner]                     
          │   ├── TableScan[t1]
          │   └── TableScan[t2]
          ├── Join[t1.age=t2.age AND t1.id≠t2.id, inner]  
          │   ├── TableScan[t1]
          │   └── TableScan[t2]
          ├── Project[t1-side cols + NULLs]               
          │   └── Join[t1.id=t2.id, anti]
          │       ├── Join[t1.age=t2.age, anti]            
          │       │   ├── TableScan[t1]
          │       │   └── TableScan[t2]
          │       └── TableScan[t2]
          └── Project[NULLs + t2-side cols]               
              └── Join[t2.id=t1.id, anti]
                  ├── Join[t2.age=t1.age, anti]           
                  │   ├── TableScan[t2]
                  │   └── TableScan[t1]
                  └── TableScan[t1] 

      Attachments

        1. image-2025-04-03-13-36-23-352.png
          83 kB
          Zhen Chen
        2. image-2025-04-03-13-37-16-575.png
          106 kB
          Zhen Chen

        Issue Links

          Activity

            People

              jensen Zhen Chen
              jensen Zhen Chen
              Votes:
              0 Vote for this issue
              Watchers:
              3 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved: