Optimize container filters in QueryParser
authorMike Rylander <mrylander@gmail.com>
Thu, 12 Sep 2013 17:13:23 +0000 (13:13 -0400)
committerDan Scott <dscott@laurentian.ca>
Thu, 12 Sep 2013 17:45:43 +0000 (13:45 -0400)
When a container filter is used at the top level of a QueryParser
query (that is, in a simple query with no OR-logic branches or explicit
nesting groups) we can use an INNER join instead of LEFT + IS NOT NULL.

On some production datasets this showed an increase in performance from
20+ seconds to 1ms for the core query.

Signed-off-by: Mike Rylander <mrylander@gmail.com>
Signed-off-by: Dan Scott <dscott@laurentian.ca>
Open-ILS/src/perlmods/lib/OpenILS/Application/Storage/Driver/Pg/QueryParser.pm

index 544dba9..e4e237c 100644 (file)
@@ -1096,12 +1096,13 @@ sub flatten {
                         }
                         $with .= "     )";
 
-                        $from .= "\n" . ${spc} x 3 . "LEFT JOIN container_${filter_alias} ON container_${filter_alias}.record = m.source";
+                        my $optimize_join = 1 if $self->top_plan and !$NOT;
+                        $from .= "\n" . ${spc} x 3 . ( $optimize_join ? 'INNER' : 'LEFT') . " JOIN container_${filter_alias} ON container_${filter_alias}.record = m.source";
 
-                        my $spcdepth = $self->plan_level + 5;
-
-                        $where .= $joiner if $where ne '';
-                        $where .= "${NOT}(container_${filter_alias} IS NOT NULL)";
+                        if (!$optimize_join) {
+                            $where .= $joiner if $where ne '';
+                            $where .= "(container_${filter_alias} IS " . ( $NOT ? 'NULL)' : 'NOT NULL)');
+                        }
                     }
                 }
             } elsif ($filter->name eq 'record_list') {