Commit ba608ef2 authored by craig[bot]'s avatar craig[bot]

Merge #48629

48629: opt: move InlineConstVar to inline.opt r=RaduBerinde a=DrewKimball

Previously, InlineConstVar was located in select.opt, which meant it
fired after other rules pushed filters down.
This patch moves InlineConstVar to inline.opt and sets it to high
priority so it will fire before filter push-down. This gives it
access to constant filters before they're pushed down.

Release note (sql change): Improve optimizer's ability to inline
constant values in filter conditions.
Co-authored-by: default avatarDrew Kimball <[email protected]>
parents 2fd6663f 7c66fcee
......@@ -15,6 +15,19 @@
# case.
# =============================================================================
# InlineConstVar inlines variables which are restricted to be constant, as in
# SELECT * FROM foo WHERE a = 4 AND a IN (1, 2, 3, 4).
# =>
# SELECT * FROM foo WHERE a = 4 AND 4 IN (1, 2, 3, 4).
# Note that a single iteration of this rule might not be sufficient to inline
# all variables, in which case it will trigger itself again.
#
# This rule is high priority so that it runs before filter pushdown.
[InlineConstVar, Normalize, HighPriority]
(Select $input:* $filters:* & (CanInlineConstVar $filters))
=>
(Select $input (InlineConstVar $filters))
# InlineProjectConstants finds variable references in Projections expressions
# that refer to constant input values, and then inlines those constant values
# in place of the corresponding variable references. This sometimes allows
......
......@@ -297,17 +297,6 @@ $input
=>
(Select $input (RemoveFiltersItem $filters $item))
# InlineConstVar inlines variables which are restricted to be constant, as in
# SELECT * FROM foo WHERE a = 4 AND a IN (1, 2, 3, 4).
# =>
# SELECT * FROM foo WHERE a = 4 AND 4 IN (1, 2, 3, 4).
# Note that a single iteration of this rule might not be sufficient to inline
# all variables, in which case it will trigger itself again.
[InlineConstVar, Normalize]
(Select $input:* $filters:* & (CanInlineConstVar $filters))
=>
(Select $input (InlineConstVar $filters))
# PushSelectIntoProjectSet pushes filters into a ProjectSet. In particular,
# the filters that are bound to the input columns of the ProjectSet are
# pushed down into it, in hopes of being pushed down further into joins
......
......@@ -10,6 +10,150 @@ exec-ddl
CREATE TABLE computed (a INT PRIMARY KEY, b INT, c INT AS (a+b+1) STORED)
----
exec-ddl
CREATE TABLE b (k INT PRIMARY KEY, i INT, f FLOAT, s STRING NOT NULL, j JSON)
----
# --------------------------------------------------
# InlineConstVar
# --------------------------------------------------
norm expect=InlineConstVar
SELECT k FROM b WHERE i=5 AND i IN (1, 2, 3, 4, 5)
----
project
├── columns: k:1!null
├── key: (1)
└── select
├── columns: k:1!null i:2!null
├── key: (1)
├── fd: ()-->(2)
├── scan b
│ ├── columns: k:1!null i:2
│ ├── key: (1)
│ └── fd: (1)-->(2)
└── filters
└── i:2 = 5 [outer=(2), constraints=(/2: [/5 - /5]; tight), fd=()-->(2)]
norm expect=InlineConstVar
SELECT k FROM b WHERE i=8 AND 3 = mod(i, 5)
----
project
├── columns: k:1!null
├── key: (1)
└── select
├── columns: k:1!null i:2!null
├── key: (1)
├── fd: ()-->(2)
├── scan b
│ ├── columns: k:1!null i:2
│ ├── key: (1)
│ └── fd: (1)-->(2)
└── filters
└── i:2 = 8 [outer=(2), constraints=(/2: [/8 - /8]; tight), fd=()-->(2)]
norm expect=InlineConstVar
SELECT k FROM b WHERE i=5 AND i IN (1, 2, 3, 4)
----
values
├── columns: k:1!null
├── cardinality: [0 - 0]
├── key: ()
└── fd: ()-->(1)
# Case that requires multiple iterations to fully inline.
norm expect=InlineConstVar
SELECT * FROM xy WHERE x=y AND y=4 AND x IN (1, 2, 3, 4)
----
select
├── columns: x:1!null y:2!null
├── cardinality: [0 - 1]
├── key: ()
├── fd: ()-->(1,2)
├── scan xy
│ ├── columns: x:1!null y:2
│ ├── key: (1)
│ └── fd: (1)-->(2)
└── filters
├── x:1 = 4 [outer=(1), constraints=(/1: [/4 - /4]; tight), fd=()-->(1)]
└── y:2 = 4 [outer=(2), constraints=(/2: [/4 - /4]; tight), fd=()-->(2)]
norm expect=InlineConstVar
SELECT * FROM xy WHERE x=y AND y=4 AND x=3
----
values
├── columns: x:1!null y:2!null
├── cardinality: [0 - 0]
├── key: ()
└── fd: ()-->(1,2)
# Can't inline composite types.
norm expect-not=InlineConstVar
SELECT * FROM (VALUES (0.0), (0.00), (0.000)) AS v (x) WHERE x = 0 AND x::STRING = '0.00';
----
select
├── columns: x:1!null
├── cardinality: [0 - 3]
├── fd: ()-->(1)
├── values
│ ├── columns: column1:1!null
│ ├── cardinality: [3 - 3]
│ ├── (0.0,)
│ ├── (0.00,)
│ └── (0.000,)
└── filters
├── column1:1 = 0 [outer=(1), constraints=(/1: [/0 - /0]; tight), fd=()-->(1)]
└── column1:1::STRING = '0.00' [outer=(1)]
# The rule should trigger, but not inline the composite type.
norm expect=InlineConstVar
SELECT * FROM (VALUES (0.0, 'a'), (0.00, 'b'), (0.000, 'b')) AS v (x, y) WHERE x = 0 AND x::STRING = '0.00' AND y = 'b' AND y IN ('a', 'b');
----
select
├── columns: x:1!null y:2!null
├── cardinality: [0 - 3]
├── fd: ()-->(1,2)
├── values
│ ├── columns: column1:1!null column2:2!null
│ ├── cardinality: [3 - 3]
│ ├── (0.0, 'a')
│ ├── (0.00, 'b')
│ └── (0.000, 'b')
└── filters
├── column1:1 = 0 [outer=(1), constraints=(/1: [/0 - /0]; tight), fd=()-->(1)]
├── column1:1::STRING = '0.00' [outer=(1)]
└── column2:2 = 'b' [outer=(2), constraints=(/2: [/'b' - /'b']; tight), fd=()-->(2)]
# Ensure that InlineConstVar fires before filter pushdown rules.
norm expect=InlineConstVar
SELECT * FROM a INNER JOIN xy ON True WHERE y=10 AND i<y
----
inner-join (cross)
├── columns: k:1!null i:2!null f:3 s:4 j:5 x:6!null y:7!null
├── key: (1,6)
├── fd: ()-->(7), (1)-->(2-5)
├── select
│ ├── columns: k:1!null i:2!null f:3 s:4 j:5
│ ├── key: (1)
│ ├── fd: (1)-->(2-5)
│ ├── scan a
│ │ ├── columns: k:1!null i:2 f:3 s:4 j:5
│ │ ├── key: (1)
│ │ └── fd: (1)-->(2-5)
│ └── filters
│ └── i:2 < 10 [outer=(2), constraints=(/2: (/NULL - /9]; tight)]
├── select
│ ├── columns: x:6!null y:7!null
│ ├── key: (6)
│ ├── fd: ()-->(7)
│ ├── scan xy
│ │ ├── columns: x:6!null y:7
│ │ ├── key: (6)
│ │ └── fd: (6)-->(7)
│ └── filters
│ └── y:7 = 10 [outer=(7), constraints=(/7: [/10 - /10]; tight), fd=()-->(7)]
└── filters (true)
# --------------------------------------------------
# InlineProjectConstants
# --------------------------------------------------
......
......@@ -1076,7 +1076,7 @@ inner-join (hash)
├── key: (6)
├── fd: ()-->(3,4,7), (1)-->(2,5), (1)==(6), (6)==(1)
├── select
│ ├── columns: k:1!null i:2 f:3!null s:4!null j:5
│ ├── columns: k:1!null i:2!null f:3!null s:4!null j:5
│ ├── key: (1)
│ ├── fd: ()-->(3,4), (1)-->(2,5)
│ ├── scan a
......@@ -1085,7 +1085,8 @@ inner-join (hash)
│ │ └── fd: (1)-->(2-5)
│ └── filters
│ ├── f:3 = 1.1 [outer=(3), constraints=(/3: [/1.1 - /1.1]; tight), fd=()-->(3)]
│ └── s:4 = 'foo' [outer=(4), constraints=(/4: [/'foo' - /'foo']; tight), fd=()-->(4)]
│ ├── s:4 = 'foo' [outer=(4), constraints=(/4: [/'foo' - /'foo']; tight), fd=()-->(4)]
│ └── i:2 < 10 [outer=(2), constraints=(/2: (/NULL - /9]; tight)]
├── select
│ ├── columns: x:6!null y:7!null
│ ├── key: (6)
......@@ -1097,8 +1098,7 @@ inner-join (hash)
│ └── filters
│ └── y:7 = 10 [outer=(7), constraints=(/7: [/10 - /10]; tight), fd=()-->(7)]
└── filters
├── k:1 = x:6 [outer=(1,6), constraints=(/1: (/NULL - ]; /6: (/NULL - ]), fd=(1)==(6), (6)==(1)]
└── i:2 < y:7 [outer=(2,7), constraints=(/2: (/NULL - ]; /7: (/NULL - ])]
└── k:1 = x:6 [outer=(1,6), constraints=(/1: (/NULL - ]; /6: (/NULL - ]), fd=(1)==(6), (6)==(1)]
norm
SELECT * FROM a, xy WHERE a.i=100 AND $1>'2000-01-01T1:00:00' AND xy.x=a.k
......@@ -1410,117 +1410,6 @@ values
├── key: ()
└── fd: ()-->(1)
# --------------------------------------------------
# InlineConstVar
# --------------------------------------------------
norm expect=InlineConstVar
SELECT k FROM b WHERE i=5 AND i IN (1, 2, 3, 4, 5)
----
project
├── columns: k:1!null
├── key: (1)
└── select
├── columns: k:1!null i:2!null
├── key: (1)
├── fd: ()-->(2)
├── scan b
│ ├── columns: k:1!null i:2
│ ├── key: (1)
│ └── fd: (1)-->(2)
└── filters
└── i:2 = 5 [outer=(2), constraints=(/2: [/5 - /5]; tight), fd=()-->(2)]
norm expect=InlineConstVar
SELECT k FROM b WHERE i=8 AND 3 = mod(i, 5)
----
project
├── columns: k:1!null
├── key: (1)
└── select
├── columns: k:1!null i:2!null
├── key: (1)
├── fd: ()-->(2)
├── scan b
│ ├── columns: k:1!null i:2
│ ├── key: (1)
│ └── fd: (1)-->(2)
└── filters
└── i:2 = 8 [outer=(2), constraints=(/2: [/8 - /8]; tight), fd=()-->(2)]
norm expect=InlineConstVar
SELECT k FROM b WHERE i=5 AND i IN (1, 2, 3, 4)
----
values
├── columns: k:1!null
├── cardinality: [0 - 0]
├── key: ()
└── fd: ()-->(1)
# Case that requires multiple iterations to fully inline.
norm expect=InlineConstVar
SELECT * FROM xy WHERE x=y AND y=4 AND x IN (1, 2, 3, 4)
----
select
├── columns: x:1!null y:2!null
├── cardinality: [0 - 1]
├── key: ()
├── fd: ()-->(1,2)
├── scan xy
│ ├── columns: x:1!null y:2
│ ├── key: (1)
│ └── fd: (1)-->(2)
└── filters
├── x:1 = 4 [outer=(1), constraints=(/1: [/4 - /4]; tight), fd=()-->(1)]
└── y:2 = 4 [outer=(2), constraints=(/2: [/4 - /4]; tight), fd=()-->(2)]
norm expect=InlineConstVar
SELECT * FROM xy WHERE x=y AND y=4 AND x=3
----
values
├── columns: x:1!null y:2!null
├── cardinality: [0 - 0]
├── key: ()
└── fd: ()-->(1,2)
# Can't inline composite types.
norm expect-not=InlineConstVar
SELECT * FROM (VALUES (0.0), (0.00), (0.000)) AS v (x) WHERE x = 0 AND x::STRING = '0.00';
----
select
├── columns: x:1!null
├── cardinality: [0 - 3]
├── fd: ()-->(1)
├── values
│ ├── columns: column1:1!null
│ ├── cardinality: [3 - 3]
│ ├── (0.0,)
│ ├── (0.00,)
│ └── (0.000,)
└── filters
├── column1:1 = 0 [outer=(1), constraints=(/1: [/0 - /0]; tight), fd=()-->(1)]
└── column1:1::STRING = '0.00' [outer=(1)]
# The rule should trigger, but not inline the composite type.
norm expect=InlineConstVar
SELECT * FROM (VALUES (0.0, 'a'), (0.00, 'b'), (0.000, 'b')) AS v (x, y) WHERE x = 0 AND x::STRING = '0.00' AND y = 'b' AND y IN ('a', 'b');
----
select
├── columns: x:1!null y:2!null
├── cardinality: [0 - 3]
├── fd: ()-->(1,2)
├── values
│ ├── columns: column1:1!null column2:2!null
│ ├── cardinality: [3 - 3]
│ ├── (0.0, 'a')
│ ├── (0.00, 'b')
│ └── (0.000, 'b')
└── filters
├── column1:1 = 0 [outer=(1), constraints=(/1: [/0 - /0]; tight), fd=()-->(1)]
├── column1:1::STRING = '0.00' [outer=(1)]
└── column2:2 = 'b' [outer=(2), constraints=(/2: [/'b' - /'b']; tight), fd=()-->(2)]
# --------------------------------------------------
# PushSelectIntoProjectSet
# --------------------------------------------------
......
......@@ -142,10 +142,8 @@ update abc
│ └── column11:11 => abc.c:3
└── project
├── columns: column10:10 column11:11 abc.a:4!null abc.b:5 abc.c:6 old.a:7!null old.b:8 old.c:9
├── inner-join (merge)
├── inner-join (cross)
│ ├── columns: abc.a:4!null abc.b:5 abc.c:6 old.a:7!null old.b:8 old.c:9
│ ├── left ordering: +4
│ ├── right ordering: +7
│ ├── scan abc
│ │ ├── columns: abc.a:4!null abc.b:5 abc.c:6
│ │ └── constraint: /4: [/2 - /2]
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment