Skip to content

Commit 23e1618

Browse files
craig[bot]mgartnerdhartunian
committed
151337: opt: eliminate barrier expressions at the root r=mgartner a=mgartner `BarrierExpr`s are now eliminated at the root of the expression tree. These barriers are typically pulled up the expression tree by normalization rules. At the root, they are useless, as their purpose is an optimization barrier which prevents filters from being pushed into their input. These barriers also prevented the placeholder-fast path from applying, incurring extra overhead for queries on RLS tables. Barrier elimination occurs in `optbuilder` when building the canonical plan. It cannot be codified as a normalization rule because the `Construct...` functions have no concept of a root expression when they are invoked. The tree is built bottom-up so the root expression is only known by callers, when all other expressions have been built. Barrier expressions are never added nor pulled up the tree during exploration, so removing a barrier at the root in the canonical plan should be sufficient in eliminating a barriers at the root in all optimized plans. Fixes #149694 Release note (performance improvement): Some types of simple queries that query a table with RLS enabled are now more efficiently executed. 151495: sql: add goroutine IDs to text trace output in logs r=alyshanjahani-crl,arulajmani,yuzefovich a=dhartunian when outputting a transaction trace in text format into the logs, we will now include the goroutine ID in the line with the operation like this: ``` === operation:foo gid:123 <other tags> ``` Epic: None Release note: None Co-authored-by: Marcus Gartner <[email protected]> Co-authored-by: David Hartunian <[email protected]>
3 parents c0934ae + 3fa8423 + ce859f8 commit 23e1618

File tree

10 files changed

+304
-225
lines changed

10 files changed

+304
-225
lines changed

pkg/sql/opt/norm/testdata/rules/barrier

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@ CREATE TABLE xy (x INT PRIMARY KEY, y INT);
66
# EliminateRedundantBarrier
77
# --------------------------------------------------
88

9-
# TODO(sql-queries): for simplicity, we should eliminate the barrier expression
10-
# at the root in this case. It serves no purpose because the filters were able
11-
# to permeate it.
9+
# NOTE: Barriers at the root are eliminated by optbuilder, not a normalization
10+
# rule. exprnorm bypasses optbuilder, so the root barrier remains in the output
11+
# of this test case.
1212
exprnorm expect=EliminateRedundantBarrier
1313
(Barrier
1414
(Barrier

pkg/sql/opt/norm/testdata/rules/join

Lines changed: 142 additions & 167 deletions
Large diffs are not rendered by default.

pkg/sql/opt/norm/testdata/rules/project

Lines changed: 23 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -2055,19 +2055,17 @@ SET ROLE alice;
20552055
norm expect=PushLeakproofProjectionsIntoPermeableBarrier
20562056
SELECT CASE WHEN y = 20 THEN 10 ELSE 0 END FROM rls
20572057
----
2058-
barrier
2058+
project
20592059
├── columns: case:6
2060-
└── project
2061-
├── columns: case:6
2062-
├── select
2063-
│ ├── columns: y:2 alice_has_access:3!null
2064-
│ ├── fd: ()-->(3)
2065-
│ ├── scan rls
2066-
│ │ └── columns: y:2 alice_has_access:3
2067-
│ └── filters
2068-
│ └── alice_has_access:3 [outer=(3), constraints=(/3: [/true - /true]; tight), fd=()-->(3)]
2069-
└── projections
2070-
└── CASE WHEN y:2 = 20 THEN 10 ELSE 0 END [as=case:6, outer=(2)]
2060+
├── select
2061+
│ ├── columns: y:2 alice_has_access:3!null
2062+
│ ├── fd: ()-->(3)
2063+
│ ├── scan rls
2064+
│ │ └── columns: y:2 alice_has_access:3
2065+
│ └── filters
2066+
│ └── alice_has_access:3 [outer=(3), constraints=(/3: [/true - /true]; tight), fd=()-->(3)]
2067+
└── projections
2068+
└── CASE WHEN y:2 = 20 THEN 10 ELSE 0 END [as=case:6, outer=(2)]
20712069

20722070
# Only some expressions in projection are leakproof
20732071
norm expect-not=PushLeakproofProjectionsIntoPermeableBarrier
@@ -2122,23 +2120,19 @@ project
21222120
norm expect=PushLeakproofProjectionsIntoPermeableBarrier
21232121
SELECT x, y, CASE WHEN y = 20 THEN 10 ELSE 0 END FROM rls
21242122
----
2125-
barrier
2123+
project
21262124
├── columns: x:1!null y:2 case:6
21272125
├── key: (1)
21282126
├── fd: (1)-->(2), (2)-->(6)
2129-
└── project
2130-
├── columns: case:6 x:1!null y:2
2131-
├── key: (1)
2132-
├── fd: (1)-->(2), (2)-->(6)
2133-
├── select
2134-
│ ├── columns: x:1!null y:2 alice_has_access:3!null
2135-
│ ├── key: (1)
2136-
│ ├── fd: ()-->(3), (1)-->(2)
2137-
│ ├── scan rls
2138-
│ │ ├── columns: x:1!null y:2 alice_has_access:3
2139-
│ │ ├── key: (1)
2140-
│ │ └── fd: (1)-->(2,3)
2141-
│ └── filters
2142-
│ └── alice_has_access:3 [outer=(3), constraints=(/3: [/true - /true]; tight), fd=()-->(3)]
2143-
└── projections
2144-
└── CASE WHEN y:2 = 20 THEN 10 ELSE 0 END [as=case:6, outer=(2)]
2127+
├── select
2128+
│ ├── columns: x:1!null y:2 alice_has_access:3!null
2129+
│ ├── key: (1)
2130+
│ ├── fd: ()-->(3), (1)-->(2)
2131+
│ ├── scan rls
2132+
│ │ ├── columns: x:1!null y:2 alice_has_access:3
2133+
│ │ ├── key: (1)
2134+
│ │ └── fd: (1)-->(2,3)
2135+
│ └── filters
2136+
│ └── alice_has_access:3 [outer=(3), constraints=(/3: [/true - /true]; tight), fd=()-->(3)]
2137+
└── projections
2138+
└── CASE WHEN y:2 = 20 THEN 10 ELSE 0 END [as=case:6, outer=(2)]

pkg/sql/opt/norm/testdata/rules/select

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2689,21 +2689,17 @@ project
26892689
norm expect=PushLeakproofFiltersIntoPermeableBarrier
26902690
SELECT * FROM rls WHERE y = 20;
26912691
----
2692-
barrier
2692+
select
26932693
├── columns: x:1!null y:2!null alice_has_access:3!null
26942694
├── key: (1)
26952695
├── fd: ()-->(2,3)
2696-
└── select
2697-
├── columns: x:1!null y:2!null alice_has_access:3!null
2698-
├── key: (1)
2699-
├── fd: ()-->(2,3)
2700-
├── scan rls
2701-
│ ├── columns: x:1!null y:2 alice_has_access:3
2702-
│ ├── key: (1)
2703-
│ └── fd: (1)-->(2,3)
2704-
└── filters
2705-
├── alice_has_access:3 [outer=(3), constraints=(/3: [/true - /true]; tight), fd=()-->(3)]
2706-
└── y:2 = 20 [outer=(2), constraints=(/2: [/20 - /20]; tight), fd=()-->(2)]
2696+
├── scan rls
2697+
│ ├── columns: x:1!null y:2 alice_has_access:3
2698+
│ ├── key: (1)
2699+
│ └── fd: (1)-->(2,3)
2700+
└── filters
2701+
├── alice_has_access:3 [outer=(3), constraints=(/3: [/true - /true]; tight), fd=()-->(3)]
2702+
└── y:2 = 20 [outer=(2), constraints=(/2: [/20 - /20]; tight), fd=()-->(2)]
27072703

27082704
# --------------------------------------------------
27092705
# NormalizeLikeAny

pkg/sql/opt/optbuilder/builder.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import (
1616
"github.com/cockroachdb/cockroach/pkg/sql/delegate"
1717
"github.com/cockroachdb/cockroach/pkg/sql/opt"
1818
"github.com/cockroachdb/cockroach/pkg/sql/opt/cat"
19+
"github.com/cockroachdb/cockroach/pkg/sql/opt/memo"
1920
"github.com/cockroachdb/cockroach/pkg/sql/opt/norm"
2021
"github.com/cockroachdb/cockroach/pkg/sql/opt/optgen/exprgen"
2122
"github.com/cockroachdb/cockroach/pkg/sql/pgwire/pgcode"
@@ -299,7 +300,12 @@ func (b *Builder) buildStmtAtRoot(stmt tree.Statement, desiredTypes []*types.T)
299300
// A "root" statement cannot refer to anything from an enclosing query, so
300301
// we always start with an empty scope.
301302
inScope := b.allocScope()
302-
return b.buildStmtAtRootWithScope(stmt, desiredTypes, inScope)
303+
outScope = b.buildStmtAtRootWithScope(stmt, desiredTypes, inScope)
304+
if b, ok := outScope.expr.(*memo.BarrierExpr); ok {
305+
// Eliminate a barrier that has been pulled up to the root of the tree.
306+
outScope.expr = b.Input
307+
}
308+
return outScope
303309
}
304310

305311
// buildStmtAtRootWithScope is similar to buildStmtAtRoot, but allows a scope to

pkg/sql/opt/optbuilder/testdata/row_level_security

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2110,15 +2110,13 @@ CREATE POLICY p1 ON ob USING (user_has_access);
21102110
norm
21112111
SELECT * FROM ob WHERE y = 20;
21122112
----
2113-
barrier
2113+
select
21142114
├── columns: x:1!null y:2!null user_has_access:3!null
2115-
└── select
2116-
├── columns: x:1!null y:2!null user_has_access:3!null
2117-
├── scan ob
2118-
│ └── columns: x:1!null y:2 user_has_access:3
2119-
└── filters
2120-
├── user_has_access:3
2121-
└── y:2 = 20
2115+
├── scan ob
2116+
│ └── columns: x:1!null y:2 user_has_access:3
2117+
└── filters
2118+
├── user_has_access:3
2119+
└── y:2 = 20
21222120

21232121
# Barrier needed. Try to expose with a division by zero error.
21242122
norm
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
exec-ddl
2+
CREATE TABLE t (
3+
a INT PRIMARY KEY,
4+
b INT,
5+
c INT,
6+
d INT,
7+
INDEX (b),
8+
INDEX (d, c)
9+
)
10+
----
11+
12+
# The fast path is conditional on having a small estimated row count. Inject
13+
# statistics so that we don't have to worry about this aspect in tests.
14+
exec-ddl
15+
ALTER TABLE t INJECT STATISTICS '[
16+
{
17+
"columns": ["a"],
18+
"created_at": "2018-05-01 1:00:00.00000+00:00",
19+
"row_count": 10,
20+
"distinct_count": 10
21+
}
22+
]'
23+
----
24+
25+
exec-ddl
26+
CREATE ROLE alice
27+
----
28+
29+
exec-ddl
30+
CREATE ROLE bob
31+
----
32+
33+
exec-ddl
34+
CREATE POLICY select_policy_alice
35+
ON t
36+
FOR SELECT
37+
TO alice
38+
USING (true)
39+
----
40+
41+
exec-ddl
42+
CREATE POLICY select_policy_bob
43+
ON t
44+
FOR SELECT
45+
TO bob
46+
USING (d = 0)
47+
----
48+
49+
exec-ddl
50+
ALTER TABLE t ENABLE ROW LEVEL SECURITY
51+
----
52+
53+
exec-ddl
54+
SET ROLE alice
55+
----
56+
57+
placeholder-fast-path
58+
SELECT a FROM t WHERE b = $1
59+
----
60+
placeholder-scan t@t_b_idx
61+
├── columns: a:1!null
62+
├── has-placeholder
63+
├── stats: [rows=9.9]
64+
├── key: (1)
65+
└── span
66+
└── $1
67+
68+
# The index on (d, c) cannot be used because d is not constrained by the query
69+
# nor the policy.
70+
placeholder-fast-path
71+
SELECT a FROM t WHERE c = $1
72+
----
73+
no fast path
74+
75+
exec-ddl
76+
SET ROLE bob
77+
----
78+
79+
# The fast path cannot be used because there is an additional filter on d that
80+
# is not pushed into an index constraint.
81+
placeholder-fast-path
82+
SELECT a FROM t WHERE b = $1
83+
----
84+
no fast path
85+
86+
placeholder-fast-path
87+
SELECT a FROM t WHERE c = $1
88+
----
89+
placeholder-scan t@t_d_c_idx
90+
├── columns: a:1!null
91+
├── has-placeholder
92+
├── stats: [rows=9.801]
93+
├── key: (1)
94+
└── span
95+
├── 0
96+
└── $1

pkg/util/tracing/span_test.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,10 +145,14 @@ func parseLine(s string) (traceLine, error) {
145145
if match == nil {
146146
return traceLine{}, errors.Newf("line doesn't match: %s", s)
147147
}
148+
text := match[3]
149+
// Strip goroutine IDs from the text for test consistency
150+
gidRe := regexp.MustCompile(` gid:\d+`)
151+
text = string(gidRe.ReplaceAll([]byte(text), nil))
148152
return traceLine{
149153
timeSinceTraceStart: match[1],
150154
timeSincePrev: match[2],
151-
text: match[3],
155+
text: text,
152156
}, nil
153157
}
154158

pkg/util/tracing/test_utils.go

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -196,16 +196,22 @@ func checkRecordingWithRedact(t T, rec tracingpb.Recording, expected string, red
196196
// After | [operation]
197197
re = regexp.MustCompile(`: .*]`)
198198
rec = string(re.ReplaceAll([]byte(rec), []byte("]")))
199-
// 5. Change all tabs to four spaces.
199+
// 5. Strip out goroutine IDs from operation lines.
200+
//
201+
// Before | "=== operation:foo gid:123 _verbose:‹1›"
202+
// After | "=== operation:foo _verbose:‹1›"
203+
re = regexp.MustCompile(` gid:\d+`)
204+
rec = string(re.ReplaceAll([]byte(rec), nil))
205+
// 6. Change all tabs to four spaces.
200206
rec = strings.ReplaceAll(rec, "\t", " ")
201-
// 6. Compute the outermost indentation.
207+
// 7. Compute the outermost indentation.
202208
indent := strings.Repeat(" ", len(rec)-len(strings.TrimLeft(rec, " ")))
203-
// 7. Outdent each line by that amount.
209+
// 8. Outdent each line by that amount.
204210
var lines []string
205211
for _, line := range strings.Split(rec, "\n") {
206212
lines = append(lines, strings.TrimPrefix(line, indent))
207213
}
208-
// 8. Stitch everything together.
214+
// 9. Stitch everything together.
209215
return strings.Join(lines, "\n")
210216
}
211217

pkg/util/tracing/tracingpb/recording.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,10 @@ func (r Recording) visitSpan(sp RecordedSpan, depth int) []traceLogData {
259259
sb.SafeString("=== operation:")
260260
sb.SafeString(redact.SafeString(sp.Operation))
261261

262+
if sp.GoroutineID != 0 {
263+
sb.Printf(" gid:%d", sp.GoroutineID)
264+
}
265+
262266
for _, tg := range sp.TagGroups {
263267
var prefix redact.RedactableString
264268
if tg.Name != AnonymousTagGroupName {

0 commit comments

Comments
 (0)