Skip to content

Commit

Permalink
executor: use a hash for plan cache keys
Browse files Browse the repository at this point in the history
Signed-off-by: Vicent Marti <[email protected]>
  • Loading branch information
vmg committed Sep 14, 2021
1 parent 94ec73e commit 76e49e3
Show file tree
Hide file tree
Showing 5 changed files with 29 additions and 19 deletions.
1 change: 0 additions & 1 deletion go/vt/vtgate/engine/cached_size.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

19 changes: 18 additions & 1 deletion go/vt/vtgate/executor.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ package vtgate
import (
"bytes"
"context"
"crypto/sha256"
"encoding/hex"
"encoding/json"
"errors"
"fmt"
Expand All @@ -31,6 +33,7 @@ import (

"vitess.io/vitess/go/acl"
"vitess.io/vitess/go/cache"
"vitess.io/vitess/go/hack"
"vitess.io/vitess/go/mysql"
"vitess.io/vitess/go/sqltypes"
"vitess.io/vitess/go/stats"
Expand Down Expand Up @@ -1235,7 +1238,12 @@ func (e *Executor) getPlan(vcursor *vcursorImpl, sql string, comments sqlparser.
logStats.BindVariables = bindVars
}

planKey := vcursor.planPrefixKey() + ":" + query
planHash := sha256.New()
planHash.Write([]byte(vcursor.planPrefixKey()))
planHash.Write([]byte{':'})
planHash.Write(hack.StringBytes(query))
planKey := hex.EncodeToString(planHash.Sum(nil))

if plan, ok := e.plans.Get(planKey); ok {
return plan.(*engine.Plan), nil
}
Expand All @@ -1255,6 +1263,15 @@ func (e *Executor) getPlan(vcursor *vcursorImpl, sql string, comments sqlparser.
return e.checkThatPlanIsValid(stmt, plan)
}

func (e *Executor) debugGetPlan(planKey string) (*engine.Plan, bool) {
planHash := sha256.Sum256([]byte(planKey))
planHex := hex.EncodeToString(planHash[:])
if plan, ok := e.plans.Get(planHex); ok {
return plan.(*engine.Plan), true
}
return nil, false
}

// skipQueryPlanCache extracts SkipQueryPlanCache from session
func skipQueryPlanCache(safeSession *SafeSession) bool {
if safeSession == nil || safeSession.Options == nil {
Expand Down
14 changes: 7 additions & 7 deletions go/vt/vtgate/executor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1464,7 +1464,7 @@ func TestGetPlanUnnormalized(t *testing.T) {
want := []string{
"@unknown:" + query1,
}
assertCacheContains(t, r.plans, want)
assertCacheContains(t, r, want)
if logStats2.SQL != wantSQL {
t.Errorf("logstats sql want \"%s\" got \"%s\"", wantSQL, logStats2.SQL)
}
Expand All @@ -1483,7 +1483,7 @@ func TestGetPlanUnnormalized(t *testing.T) {
KsTestUnsharded + "@unknown:" + query1,
"@unknown:" + query1,
}
assertCacheContains(t, r.plans, want)
assertCacheContains(t, r, want)
if logStats4.SQL != wantSQL {
t.Errorf("logstats sql want \"%s\" got \"%s\"", wantSQL, logStats4.SQL)
}
Expand All @@ -1501,10 +1501,10 @@ func assertCacheSize(t *testing.T, c cache.Cache, expected int) {
}
}

func assertCacheContains(t *testing.T, c cache.Cache, want []string) {
func assertCacheContains(t *testing.T, e *Executor, want []string) {
t.Helper()
for _, wantKey := range want {
if _, ok := c.Get(wantKey); !ok {
if _, ok := e.debugGetPlan(wantKey); !ok {
t.Errorf("missing key in plan cache: %v", wantKey)
}
}
Expand Down Expand Up @@ -1626,7 +1626,7 @@ func TestGetPlanNormalized(t *testing.T) {
want := []string{
"@unknown:" + normalized,
}
assertCacheContains(t, r.plans, want)
assertCacheContains(t, r, want)

wantSQL := normalized + " /* comment 1 */"
if logStats1.SQL != wantSQL {
Expand Down Expand Up @@ -1673,14 +1673,14 @@ func TestGetPlanNormalized(t *testing.T) {
KsTestUnsharded + "@unknown:" + normalized,
"@unknown:" + normalized,
}
assertCacheContains(t, r.plans, want)
assertCacheContains(t, r, want)

_, err := r.getPlan(emptyvc, "syntax", makeComments(""), map[string]*querypb.BindVariable{}, false, nil)
wantErr := "syntax error at position 7 near 'syntax'"
if err == nil || err.Error() != wantErr {
t.Errorf("getPlan(syntax): %v, want %s", err, wantErr)
}
assertCacheContains(t, r.plans, want)
assertCacheContains(t, r, want)
}

func TestPassthroughDDL(t *testing.T) {
Expand Down
13 changes: 4 additions & 9 deletions go/vt/vtgate/queryz_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,23 +44,21 @@ func TestQueryzHandler(t *testing.T) {
_, err := executorExec(executor, sql, nil)
require.NoError(t, err)
executor.plans.Wait()
result, ok := executor.plans.Get("@primary:" + sql)
plan1, ok := executor.debugGetPlan("@primary:" + sql)
if !ok {
t.Fatalf("couldn't get plan from cache")
}
plan1 := result.(*engine.Plan)
plan1.ExecTime = uint64(1 * time.Millisecond)

// scatter
sql = "select id from user"
_, err = executorExec(executor, sql, nil)
require.NoError(t, err)
executor.plans.Wait()
result, ok = executor.plans.Get("@primary:" + sql)
plan2, ok := executor.debugGetPlan("@primary:" + sql)
if !ok {
t.Fatalf("couldn't get plan from cache")
}
plan2 := result.(*engine.Plan)
plan2.ExecTime = uint64(1 * time.Second)

sql = "insert into user (id, name) values (:id, :name)"
Expand All @@ -70,18 +68,15 @@ func TestQueryzHandler(t *testing.T) {
})
require.NoError(t, err)
executor.plans.Wait()
result, ok = executor.plans.Get("@primary:" + sql)
plan3, ok := executor.debugGetPlan("@primary:" + sql)
if !ok {
t.Fatalf("couldn't get plan from cache")
}
plan3 := result.(*engine.Plan)

// vindex insert from above execution
result, ok = executor.plans.Get("@primary:" + "insert into name_user_map(name, user_id) values(:name_0, :user_id_0)")
plan4, ok := executor.debugGetPlan("@primary:" + "insert into name_user_map(name, user_id) values(:name_0, :user_id_0)")
require.True(t, ok, "couldn't get plan from cache")

plan4 := result.(*engine.Plan)

// same query again should add query counts to existing plans
sql = "insert into user (id, name) values (:id, :name)"
_, err = executorExec(executor, sql, map[string]*querypb.BindVariable{
Expand Down
1 change: 0 additions & 1 deletion go/vt/vtgate/vindexes/cached_size.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 76e49e3

Please sign in to comment.