lujiajing1126 opened a new pull request #10:
URL: https://github.com/apache/skywalking-banyandb/pull/10
This PR focuses on the logical plan of the query module.
## Logical Plan
The logical plan is generated from QueryCriteria and is organized as a tree.
### Resolved and Unresolved plan/expr
We consider the `QueryCriteria` in an unresolved status (i.e. it does not
contain any metadata of the entities), and directly generate an **Unresolved**
logical plan first and further resolve it with metadata.
For example,
```go
// fieldRef is the reference to the field
// also it holds the definition/schema of the field
type fieldRef struct {
// name defines the key of the field
name string
// spec contains the index of the key in the schema, as well as the
underlying FieldSpec
spec *fieldSpec
}
func NewFieldRef(fieldName string) *fieldRef {
return &fieldRef{
name: fieldName,
}
}
```
when we create the `fieldRef`, it stays in the `Unresolved` status which
mean it does not know anything about the typing, even cannot guarantee a field
with the given name exists in the definition.
The separation of `Resolved` and `Unresolved` statuses would make it
possible to build a logical plan with DSL much easier.
```go
correctPlan, err := logical.Projection(logical.Limit(
logical.Offset(logical.OrderBy(
logical.Selection(
logical.Scan(uint64(sT.UnixNano()),
uint64(eT.UnixNano()), traceMetadata, "service_id", "trace_id",
"service_instance_id", "http.method", "service_name"),
logical.Eq(logical.NewFieldRef("http.method"),
logical.Str("GET")),
logical.Eq(logical.NewFieldRef("service_name"),
logical.Str("my_app")),
), "service_instance_id", apiv1.SortDESC,
), 10), 5,
), []string{"service_id", "trace_id"}).Analyze(schema)
```
This can be used to compare with the generated plan, which would
significantly improve the testibility. For equality test, we also introduce `T
Equal(T) bool` like method for Plan, Expr, and Metadata as suggested in
[`go-cmp` document](https://pkg.go.dev/github.com/google/go-cmp/cmp#Equal).
### Inspection
The logical plan can be printed as string,
```
+----Limit: 5
+----Offset: 10
+----OrderBy: #service_instance_id<String>, sort=DESC
+----Selection: [#http.method<String> EQ GET AND
#service_name<String> EQ my_app]
+----Scan:
startTime=1624185419600386000,endTime=1624196219600388000,Metadata{group=default,name=trace};
projection=#service_id<String>, #trace_id<String>,
#service_instance_id<String>, #http.method<String>, #service_name<String>
```
## Optimizer
Rule-based optimizer is introduced. So far, I only implement
`projectionPushDown`.
Before optimization,
```
Projection: #service_id<String>, #trace_id<String>
+----Limit: 5
+----Offset: 10
+----OrderBy: #service_instance_id<String>, sort=DESC
+----Selection: [#http.method<String> EQ GET AND
#service_name<String> EQ my_app]
+----Scan:
startTime=1624185419600386000,endTime=1624196219600388000,Metadata{group=default,name=trace};
projection=None
```
After,
```
Projection: #service_id<String>, #trace_id<String>
+----Limit: 5
+----Offset: 10
+----OrderBy: #service_instance_id<String>, sort=DESC
+----Selection: [#http.method<String> EQ GET AND
#service_name<String> EQ my_app]
+----Scan:
startTime=1624185419600386000,endTime=1624196219600388000,Metadata{group=default,name=trace};
projection=#service_id<String>, #trace_id<String>,
#service_instance_id<String>, #http.method<String>, #service_name<String>
```
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
For queries about this service, please contact Infrastructure at:
[email protected]