Map field names to array indices in scanwriter, once per query.

This commit is contained in:
Alex Roitman 2020-03-25 11:53:44 -07:00
parent 9e7766b346
commit d5132a9eae
3 changed files with 27 additions and 20 deletions

View File

@ -97,8 +97,6 @@ func (s *Server) newScanWriter(
msg: msg,
cursor: cursor,
limit: limit,
wheres: wheres,
whereins: whereins,
whereevals: whereevals,
output: output,
nofields: nofields,
@ -117,6 +115,19 @@ func (s *Server) newScanWriter(
if sw.col != nil {
sw.fmap = sw.col.FieldMap()
sw.farr = sw.col.FieldArr()
// This fills index value in wheres/whereins
// so we don't have to map string field names for each tested object
var ok bool
for _, where := range wheres {
if where.index, ok = sw.fmap[where.field]; ok {
sw.wheres = append(sw.wheres, where)
}
}
for _, wherein := range whereins {
if wherein.index, ok = sw.fmap[wherein.field]; ok {
sw.whereins = append(sw.whereins, wherein)
}
}
}
sw.fvals = make([]float64, len(sw.farr))
return sw, nil
@ -212,11 +223,8 @@ func (sw *scanWriter) fieldMatch(fields []float64, o geojson.Object) (fvals []fl
continue
}
var value float64
idx, ok := sw.fmap[where.field]
if ok {
if len(fields) > idx {
value = fields[idx]
}
if len(fields) > where.index {
value = fields[where.index]
}
if !where.match(value) {
return
@ -224,11 +232,8 @@ func (sw *scanWriter) fieldMatch(fields []float64, o geojson.Object) (fvals []fl
}
for _, wherein := range sw.whereins {
var value float64
idx, ok := sw.fmap[wherein.field]
if ok {
if len(fields) > idx {
value = fields[idx]
}
if len(fields) > wherein.index {
value = fields[wherein.index]
}
if !wherein.match(value) {
return
@ -265,13 +270,13 @@ func (sw *scanWriter) fieldMatch(fields []float64, o geojson.Object) (fvals []fl
}
continue
}
value := sw.fvals[sw.fmap[where.field]]
value := sw.fvals[where.index]
if !where.match(value) {
return
}
}
for _, wherein := range sw.whereins {
value := sw.fvals[sw.fmap[wherein.field]]
value := sw.fvals[wherein.index]
if !wherein.match(value) {
return
}

View File

@ -31,12 +31,12 @@ func BenchmarkFieldMatch(t *testing.B) {
}
sw := &scanWriter{
wheres: []whereT{
{"foo", false, 1, false, 3},
{"bar", false, 10, false, 30},
{"foo", 0, false, 1, false, 3},
{"bar", 1, false, 10, false, 30},
},
whereins: []whereinT{
{"foo", []float64{1, 2}},
{"bar", []float64{11, 25}},
{"foo", 0, []float64{1, 2}},
{"bar", 1, []float64{11, 25}},
},
fmap: map[string]int{"foo": 0, "bar": 1},
farr: []string{"bar", "foo"},

View File

@ -116,6 +116,7 @@ func lc(s1, s2 string) bool {
type whereT struct {
field string
index int
minx bool
min float64
maxx bool
@ -159,6 +160,7 @@ func zMinMaxFromWheres(wheres []whereT) (minZ, maxZ float64) {
type whereinT struct {
field string
index int
valArr []float64
}
@ -328,7 +330,7 @@ func (s *Server) parseSearchScanBaseTokens(
return
}
}
t.wheres = append(t.wheres, whereT{field, minx, min, maxx, max})
t.wheres = append(t.wheres, whereT{field, -1, minx, min, maxx, max})
continue
case "wherein":
vs = nvs
@ -359,7 +361,7 @@ func (s *Server) parseSearchScanBaseTokens(
}
valArr = append(valArr, val)
}
t.whereins = append(t.whereins, whereinT{field, valArr})
t.whereins = append(t.whereins, whereinT{field, -1, valArr})
continue
case "whereevalsha":
fallthrough