Skip to content

Commit

Permalink
Merge #57954
Browse files Browse the repository at this point in the history
57954: sql: reimplement EXPLAIN (DISTSQL) r=RaduBerinde a=RaduBerinde

#### sql: reimplement EXPLAIN (DISTSQL)

Reimplement EXPLAIN (DISTSQL) by leveraging the explainPlan code. We
emit everything that a regular EXPLAIN does, plus the diagram.

Release note (sql change): EXPLAIN (DISTSQL) has a new output schema
and format.

#### test changes


Co-authored-by: Radu Berinde <[email protected]>
  • Loading branch information
craig[bot] and RaduBerinde committed Dec 17, 2020
2 parents 66f4f5d + bb37214 commit 196501b
Show file tree
Hide file tree
Showing 46 changed files with 4,258 additions and 906 deletions.
2 changes: 1 addition & 1 deletion pkg/server/admin.go
Original file line number Diff line number Diff line change
Expand Up @@ -1593,7 +1593,7 @@ func (s *adminServer) QueryPlan(
}

explain := fmt.Sprintf(
"SELECT json FROM [EXPLAIN (DISTSQL) %s]",
"EXPLAIN (DISTSQL, JSON) %s",
strings.Trim(req.Query, ";"))
rows, err := s.server.sqlServer.internalExecutor.QueryEx(
ctx, "admin-query-plan", nil, /* txn */
Expand Down
1 change: 0 additions & 1 deletion pkg/sql/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,6 @@ go_library(
"execute.go",
"executor_statement_metrics.go",
"explain_bundle.go",
"explain_distsql.go",
"explain_plan.go",
"explain_vec.go",
"export.go",
Expand Down
8 changes: 0 additions & 8 deletions pkg/sql/catalog/colinfo/result_columns.go
Original file line number Diff line number Diff line change
Expand Up @@ -151,14 +151,6 @@ var ExplainPlanColumns = ResultColumns{
{Name: "info", Typ: types.String},
}

// ExplainDistSQLColumns are the result columns of an
// EXPLAIN (DISTSQL) statement.
var ExplainDistSQLColumns = ResultColumns{
{Name: "automatic", Typ: types.Bool},
{Name: "url", Typ: types.String},
{Name: "json", Typ: types.String, Hidden: true},
}

// ShowTraceColumns are the result columns of a SHOW [KV] TRACE statement.
var ShowTraceColumns = ResultColumns{
{Name: "timestamp", Typ: types.TimestampTZ},
Expand Down
2 changes: 1 addition & 1 deletion pkg/sql/distsql_physical_planner.go
Original file line number Diff line number Diff line change
Expand Up @@ -2793,7 +2793,7 @@ func (dsp *DistSQLPlanner) wrapPlan(planCtx *PlanningCtx, n planNode) (*Physical
if err := walkPlan(planCtx.ctx, n, planObserver{
enterNode: func(ctx context.Context, nodeName string, plan planNode) (bool, error) {
switch plan.(type) {
case *explainDistSQLNode, *explainVecNode, *explainPlanNode:
case *explainVecNode, *explainPlanNode:
// Don't continue recursing into explain nodes - they need to be left
// alone since they handle their own planning later.
return false, nil
Expand Down
23 changes: 12 additions & 11 deletions pkg/sql/distsql_physical_planner_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -404,7 +404,7 @@ func TestDistSQLRangeCachesIntegrationTest(t *testing.T) {
// of the splits and still holds the state after the first dummy query at the
// beginning of the test, which had everything on the first node.
query := `SELECT count(1) FROM "left" INNER JOIN "right" USING (num)`
row := db3.QueryRow(fmt.Sprintf(`SELECT json FROM [EXPLAIN (DISTSQL) %v]`, query))
row := db3.QueryRow(fmt.Sprintf(`EXPLAIN (DISTSQL, JSON) %v`, query))
var json string
if err := row.Scan(&json); err != nil {
t.Fatal(err)
Expand All @@ -431,7 +431,7 @@ func TestDistSQLRangeCachesIntegrationTest(t *testing.T) {
// Now assert that new plans correctly contain all the nodes. This is expected
// to be a result of the caches having been updated on the gateway by the
// previous query.
row = db3.QueryRow(fmt.Sprintf(`SELECT json FROM [EXPLAIN (DISTSQL) %v]`, query))
row = db3.QueryRow(fmt.Sprintf(`EXPLAIN (DISTSQL, JSON) %v`, query))
if err := row.Scan(&json); err != nil {
t.Fatal(err)
}
Expand Down Expand Up @@ -499,8 +499,8 @@ func TestDistSQLDeadHosts(t *testing.T) {

// Verify the plan (should include all 5 nodes).
r.CheckQueryResults(t,
"SELECT url FROM [EXPLAIN (DISTSQL) SELECT sum(xsquared) FROM t]",
[][]string{{"https://cockroachdb.github.io/distsqlplan/decode.html#eJy8k09LwzAYxu9-CnlOCu9h7bo5e5rHHXQy9SQ91OalFLamJCkoo99d1iDaIskgo8f8-T2_PG1yRC0FP-UH1kjfEYEQgzAHIQFhgYzQKFmw1lKdtlhgIz6RzghV3bTmNJ0RCqkY6RGmMntGitf8Y887zgUrEASbvNr3kkZVh1x9rQ0I29ak1-sYWUeQrflJ6-h8z0NZKi5zI0eal7fHm3V0e3b0b2JbSyVYsRgEZt2F5dFE38_jCakQT1TB4wmpMJ-ogscTUiGZqILHc6mH-E_0jnUja82jBznMywgsSrZvWctWFfysZNGH2-G2391PCNbGrkZ2sKnt0ulYf-HICccDOBrDsdvsUc-ddOKGk5BzL5zw0m1ehpjvnPDKbV6FmO_d_2rmuSbuSzZ2Z93VdwAAAP__XTV6BQ=="}},
"SELECT info FROM [EXPLAIN (DISTSQL) SELECT sum(xsquared) FROM t] WHERE info LIKE 'Diagram%'",
[][]string{{"Diagram: https://cockroachdb.github.io/distsqlplan/decode.html#eJy8k09LwzAYxu9-CnlOCu9h7bo5e5rHHXQy9SQ91OalFLamJCkoo99d1iDaIskgo8f8-T2_PG1yRC0FP-UH1kjfEYEQgzAHIQFhgYzQKFmw1lKdtlhgIz6RzghV3bTmNJ0RCqkY6RGmMntGitf8Y887zgUrEASbvNr3kkZVh1x9rQ0I29ak1-sYWUeQrflJ6-h8z0NZKi5zI0eal7fHm3V0e3b0b2JbSyVYsRgEZt2F5dFE38_jCakQT1TB4wmpMJ-ogscTUiGZqILHc6mH-E_0jnUja82jBznMywgsSrZvWctWFfysZNGH2-G2391PCNbGrkZ2sKnt0ulYf-HICccDOBrDsdvsUc-ddOKGk5BzL5zw0m1ehpjvnPDKbV6FmO_d_2rmuSbuSzZ2Z93VdwAAAP__XTV6BQ=="}},
)

// Stop node 5.
Expand All @@ -509,8 +509,8 @@ func TestDistSQLDeadHosts(t *testing.T) {
testutils.SucceedsSoon(t, runQuery)

r.CheckQueryResults(t,
"SELECT url FROM [EXPLAIN (DISTSQL) SELECT sum(xsquared) FROM t]",
[][]string{{"https://cockroachdb.github.io/distsqlplan/decode.html#eJy8k8FK7DAYhff3KS5npZCF6dRx7KouZ6Ejo64ki9j8lEKnKUkKytB3lzaItkg60qHL5M93vpySHlFpRQ_yQBbJKzgYIjCswBBDMNRGZ2StNt3YH96qdyRXDEVVN67bFgyZNoTkCFe4kpDgWb6VtCepyIBBkZNF2QtqUxyk-UgdGHaNS_6nEUTLoBv3lday0z13eW4ol06PNE8v9xcpvzw5-juxqbRRZEgNAkV7Zjlf6PtNeOZUiBaqMOGZU2G1UIUJz7le8S_Re7K1riyNXvMwTzCQysn_CFY3JqNHo7M-3C93_el-Q5F1fsr9Ylv5UXetnzAPwtEA5mM4CsK3YfMqCMdhOJ5z7esgvA6b13PMN0F4EzZv_mQW7b_PAAAA__-DuA-E"}},
"SELECT info FROM [EXPLAIN (DISTSQL) SELECT sum(xsquared) FROM t] WHERE info LIKE 'Diagram%'",
[][]string{{"Diagram: https://cockroachdb.github.io/distsqlplan/decode.html#eJy8k8FK7DAYhff3KS5npZCF6dRx7KouZ6Ejo64ki9j8lEKnKUkKytB3lzaItkg60qHL5M93vpySHlFpRQ_yQBbJKzgYIjCswBBDMNRGZ2StNt3YH96qdyRXDEVVN67bFgyZNoTkCFe4kpDgWb6VtCepyIBBkZNF2QtqUxyk-UgdGHaNS_6nEUTLoBv3lday0z13eW4ol06PNE8v9xcpvzw5-juxqbRRZEgNAkV7Zjlf6PtNeOZUiBaqMOGZU2G1UIUJz7le8S_Re7K1riyNXvMwTzCQysn_CFY3JqNHo7M-3C93_el-Q5F1fsr9Ylv5UXetnzAPwtEA5mM4CsK3YfMqCMdhOJ5z7esgvA6b13PMN0F4EzZv_mQW7b_PAAAA__-DuA-E"}},
)

// Stop node 2; note that no range had replicas on both 2 and 5.
Expand All @@ -519,8 +519,8 @@ func TestDistSQLDeadHosts(t *testing.T) {
testutils.SucceedsSoon(t, runQuery)

r.CheckQueryResults(t,
"SELECT url FROM [EXPLAIN (DISTSQL) SELECT sum(xsquared) FROM t]",
[][]string{{"https://cockroachdb.github.io/distsqlplan/decode.html#eJy8kkFLwzAUx-9-CvmfFHIwXZ3QUz3uoJOpJ8khNo9S6JrykoIy-t2lDaItkk02dkxe_r_fe-Ht0FhDj3pLDtkbJAQWEEihBFq2BTlneSiFhyvzgexGoGrazg_XSqCwTMh28JWvCRle9HtNG9KGGAKGvK7qEd5ytdX8mXsIrDufXeYJVC9gO_9N68XhnvuyZCq1tzPN8-vDVS6vD0b_ELvGsiEmMwGq_sRyeab_2-M5ZoTkTCPs8ZxqBf5Ab8i1tnE0W4UpTwmQKSlskbMdF_TEthjh4bgeX48XhpwPVRkOqyaUhrZ-h2U0nEzCch5OouG7uHkRDafxcHpM27fR8DJuXv7LrPqLrwAAAP__vMyldA=="}},
"SELECT info FROM [EXPLAIN (DISTSQL) SELECT sum(xsquared) FROM t] WHERE info LIKE 'Diagram%'",
[][]string{{"Diagram: https://cockroachdb.github.io/distsqlplan/decode.html#eJy8kkFLwzAUx-9-CvmfFHIwXZ3QUz3uoJOpJ8khNo9S6JrykoIy-t2lDaItkk02dkxe_r_fe-Ht0FhDj3pLDtkbJAQWEEihBFq2BTlneSiFhyvzgexGoGrazg_XSqCwTMh28JWvCRle9HtNG9KGGAKGvK7qEd5ytdX8mXsIrDufXeYJVC9gO_9N68XhnvuyZCq1tzPN8-vDVS6vD0b_ELvGsiEmMwGq_sRyeab_2-M5ZoTkTCPs8ZxqBf5Ab8i1tnE0W4UpTwmQKSlskbMdF_TEthjh4bgeX48XhpwPVRkOqyaUhrZ-h2U0nEzCch5OouG7uHkRDafxcHpM27fR8DJuXv7LrPqLrwAAAP__vMyldA=="}},
)
}

Expand Down Expand Up @@ -575,7 +575,8 @@ func TestDistSQLDrainingHosts(t *testing.T) {

const query = "SELECT count(*) FROM NUMS"
expectPlan := func(expectedPlan [][]string) {
planQuery := fmt.Sprintf(`SELECT url FROM [EXPLAIN (DISTSQL) %s]`, query)
t.Helper()
planQuery := fmt.Sprintf(`SELECT info FROM [EXPLAIN (DISTSQL) %s] WHERE info LIKE 'Diagram%%'`, query)
testutils.SucceedsSoon(t, func() error {
resultPlan := r.QueryStr(t, planQuery)
if !reflect.DeepEqual(resultPlan, expectedPlan) {
Expand All @@ -586,14 +587,14 @@ func TestDistSQLDrainingHosts(t *testing.T) {
}

// Verify distribution.
expectPlan([][]string{{"https://cockroachdb.github.io/distsqlplan/decode.html#eJyskd-Lm0AQx9_7V8g8mbKHWZO-7NMd1xSEnF7Vo4UgYesOIphduz-gJfi_F7WQGBKblj46O9_5fJw5gvneAINss908557TjfcpTV683ebr6_Ypij3_Y5Tl2eftwvvdUionrf9-MfZJdzAFEJBKYMwPaIDtgAKBEAoCrVYlGqN0Xz4OTZH4AWxJoJats325IFAqjcCOYGvbIDDI-bcGU-QCdbAEAgItr5thdM97bHV94PonEMhaLg3zHoIemTjLvFhJhKIjoJw9EYzlFQKjHbnf4qmqNFbcKh2EU4nn5C3O92nyJfMXN1nhTdYJ4aTSAjWKyfyim7dZT22yt5d9FOf-I70ts5rI0PvXT-9Zf0Af_mH9f7A4--HVf13_FVaKplXS4MUZrk9e9udBUeF4S6OcLvFVq3LAjJ_JkBsKAo0dX-n4EcnxqRc8D9PZcDgJ08twOBv-ME9ezYbX8-H1X2kX3btfAQAA__9aEHOO"}})
expectPlan([][]string{{"Diagram: https://cockroachdb.github.io/distsqlplan/decode.html#eJyskVFrnEAQx9_7KZaBkruy4W6968s-JSSWSo2makghSNi6UxF01-6u0HL43YtaSAw5ey19dHZ-8_85cwD7vQYOqR_6Vxmp1DdNPiTxDXnwv9yGl0FEVtdBmqWfwzX53VPoTrnVu_XUp7rG5uT-o5_4Ex0Gn3xydl2J0ojm7RlQUFpiJBq0wB-AAQUPcgqt0QVaq81QPoxNgfwBfEuhUm3nhnJOodAGgR_AVa5G4JCJrzUmKCSazRYoSHSiqsfRg8pFa6pGmJ9AIW2Fspycb4bIuHOcRFoh5D0F3bmnBOtEicBZT0-3uCxLg6Vw2my8ucRVfBdlj0l8n67WR7O8o1lPEZ3SRqJBOZuf98s2-7lNenfzGETZ6oIdl9nNZNjp62enrH_Dzv9h_X-wePbDu_-6_leyErStVhZfnOH1ydvhPChLnG5pdWcKvDW6GGOmz3jkxoJE66ZXNn0EanoaBJ_DbBH2ZjB7CXuL8Pvl5N0ivF-G93-lnfdvfgUAAP__wBp72w=="}})

// Drain the second node and expect the query to be planned on only the
// first node.
distServer := tc.Server(1).DistSQLServer().(*distsql.ServerImpl)
distServer.Drain(ctx, 0 /* flowDrainWait */, nil /* reporter */)

expectPlan([][]string{{"https://cockroachdb.github.io/distsqlplan/decode.html#eJyUkM9Kw0AYxO8-xTKnVlba9LgnS60QqElNIgolyJp8hEC6G_cPKCHvLkkErVDR4843M79hO9jXBgLpdrfdZMybht0m8R07bJ_2u3UYsdlNmGbp_W7OPi2F9srNLueTT_mjzcGhdEmRPJKFOCBAztEaXZC12gxSNxrC8g1iyVGr1rtBzjkKbQiig6tdQxDI5EtDCcmSzGIJjpKcrJuxdmBdt6Y-SvMOjrSVygp2BY7YO8EirQh5z6G9--q3TlYEEfT87xvWVWWokk6bRXA6YRM_RNlzEj-ms_lZ1uo_rIRsq5WlE8655mWfc1BZ0fSnVntT0N7oYsRMz3jMjUJJ1k3XYHqEajoNA7-Hg1_Dqx_hvL_4CAAA__-lY7ge"}})
expectPlan([][]string{{"Diagram: https://cockroachdb.github.io/distsqlplan/decode.html#eJyUkF9LwzAUxd_9FOGCbJPI1j3mybFVLNZ2tpUJo0hsr6XQJjV_QBn97tJG0AkTfcy553fOIQfQrw0wSP3QX2ekFi-SXCfxHdn7j9twFURkugnSLL0PZ-TTU0grzPRi5nzCtjonuxs_8R0dBrc-mWxqXinenk-AgpAlRrxFDWwPHuQUOiUL1FqqQTqMhqB8A7agUIvOmkHOKRRSIbADmNo0CAwy_txggrxENV8AhRINr5sxdphx1am65eodKKQdF5qRS6AQW8NIJAVC3lOQ1nzla8MrBOb19O8bVlWlsOJGqrl3PGEdP0TZUxLv0unsZNfyP10J6k4KjUc9p5IXfU4Bywrdn2ppVYFbJYuxxj3jkRuFErVxV889AuFOw8DvsPcrvPwB5_3ZRwAAAP__flPAaw=="}})

// Verify correctness.
var res int
Expand Down
23 changes: 13 additions & 10 deletions pkg/sql/distsql_spec_exec_factory.go
Original file line number Diff line number Diff line change
Expand Up @@ -748,10 +748,6 @@ func (e *distSQLSpecExecFactory) ConstructExplain(
if options.Flags[tree.ExplainFlagEnv] {
return nil, errors.New("ENV only supported with (OPT) option")
}
if options.Mode == tree.ExplainPlan {
// TODO(radu): all we need to do here is wrap an explainPlanNode.
return nil, unimplemented.NewWithIssue(47473, "experimental opt-driven distsql planning: explain plan")
}

// We cannot create the explained plan in the same PlanInfrastructure with the
// "outer" plan. Create a separate factory.
Expand All @@ -761,14 +757,21 @@ func (e *distSQLSpecExecFactory) ConstructExplain(
return nil, err
}

// TODO(yuzefovich): make sure to return the same nice error in some
// variants of EXPLAIN when subqueries are present as we do in the old path.
p := plan.(*explain.Plan).WrappedPlan.(*planComponents)
explain, err := constructExplainDistSQLOrVecNode(options, stmtType, p, e.planner)
if err != nil {
return nil, err
var explainNode planNode
if options.Mode == tree.ExplainVec {
explainNode = &explainVecNode{
options: options,
plan: *p,
}
} else {
explainNode = &explainPlanNode{
options: options,
flags: explain.MakeFlags(options),
plan: plan.(*explain.Plan),
}
}
explainNode := explain.(planNode)

physPlan, err := e.dsp.wrapPlan(e.getPlanCtx(cannotDistribute), explainNode)
if err != nil {
return nil, err
Expand Down
26 changes: 0 additions & 26 deletions pkg/sql/exec_factory_util.go
Original file line number Diff line number Diff line change
Expand Up @@ -111,32 +111,6 @@ func makeScanColumnsConfig(table cat.Table, cols exec.TableColumnOrdinalSet) sca
return colCfg
}

func constructExplainDistSQLOrVecNode(
options *tree.ExplainOptions, stmtType tree.StatementType, p *planComponents, planner *planner,
) (exec.Node, error) {
if options.Flags[tree.ExplainFlagEnv] {
return nil, errors.New("ENV only supported with (OPT) option")
}

switch options.Mode {
case tree.ExplainDistSQL:
return &explainDistSQLNode{
options: options,
plan: *p,
stmtType: stmtType,
}, nil

case tree.ExplainVec:
return &explainVecNode{
options: options,
plan: *p,
}, nil

default:
panic(errors.AssertionFailedf("unsupported explain mode %v", options.Mode))
}
}

// getResultColumnsForSimpleProject populates result columns for a simple
// projection. It supports two configurations:
// 1. colNames and resultTypes are non-nil. resultTypes indicates the updated
Expand Down
107 changes: 0 additions & 107 deletions pkg/sql/explain_distsql.go

This file was deleted.

Loading

0 comments on commit 196501b

Please sign in to comment.