From 52288fafdbccfbf6c35f9f872793b1f01c69639c Mon Sep 17 00:00:00 2001 From: Andres Taylor Date: Thu, 19 Sep 2024 09:56:25 +0200 Subject: [PATCH 1/5] make sure to run on go 1.23 Signed-off-by: Andres Taylor --- Makefile | 17 +++++++++++++++-- go.mod | 4 ++-- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index 5c2a474..3ef981c 100644 --- a/Makefile +++ b/Makefile @@ -1,8 +1,21 @@ .PHONY: all build test tidy clean vitess-tester vtbenchstat GO := go - -default: build +REQUIRED_GO_VERSION := 1.23 + +# Version check +check_version: + @GO_VERSION=$$($(GO) version | awk '{print $$3}' | sed 's/go//'); \ + MAJOR_VERSION=$$(echo $$GO_VERSION | cut -d. -f1); \ + MINOR_VERSION=$$(echo $$GO_VERSION | cut -d. -f2); \ + if [ "$$MAJOR_VERSION" -eq 1 ] && [ "$$MINOR_VERSION" -lt 23 ]; then \ + echo "Error: Go version $(REQUIRED_GO_VERSION) or higher is required. Current version is $$GO_VERSION"; \ + exit 1; \ + else \ + echo "Go version is acceptable: $$GO_VERSION"; \ + fi + +default: check_version build build: vitess-tester vtbenchstat diff --git a/go.mod b/go.mod index 43dbcb1..39d6b50 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/vitessio/vitess-tester -go 1.22.5 +go 1.23.1 require ( github.com/pingcap/errors v0.11.5-0.20221009092201-b66cddb77c32 @@ -9,6 +9,7 @@ require ( ) require ( + github.com/alecthomas/chroma v0.10.0 github.com/jstemmer/go-junit-report/v2 v2.1.0 github.com/olekukonko/tablewriter v0.0.5 golang.org/x/term v0.22.0 @@ -26,7 +27,6 @@ require ( github.com/DataDog/go-tuf v1.1.0-0.5.2 // indirect github.com/DataDog/sketches-go v1.4.6 // indirect github.com/Microsoft/go-winio v0.6.2 // indirect - github.com/alecthomas/chroma v0.10.0 // indirect github.com/aquarapid/vaultlib v0.5.1 // indirect github.com/armon/go-metrics v0.4.1 // indirect github.com/beorn7/perks v1.0.1 // indirect From a1cff6d4dfd270c653a3ff2a418db88a94b82d83 Mon Sep 17 00:00:00 2001 From: Andres Taylor Date: Thu, 19 Sep 2024 11:28:16 +0200 Subject: [PATCH 2/5] also look at shards queried Signed-off-by: Andres Taylor --- README.md | 10 ++++ src/cmd/vtbenchstat/vtbenchstat.go | 95 ++++++++++++++++++++---------- 2 files changed, 73 insertions(+), 32 deletions(-) diff --git a/README.md b/README.md index 759787a..78541ac 100644 --- a/README.md +++ b/README.md @@ -4,10 +4,18 @@ Vitess tester tests Vitess using the same test files as the [MySQL Test Framewor ## Install +If you only want the `vitess-tester` binary, install it using the following command: + ``` go install github.com/vitessio/vitess-tester@latest ``` +The `vtbenchstat` binary can be had by running: + +``` +go install github.com/vitessio/vitess-tester/src/cmd/vtbenchstat@latest +``` + ## Testing methodology To ensure compatibility and correctness, our testing strategy involves running identical queries against both MySQL and vtgate, then comparing the results and errors from the two systems. This approach helps us verify that vtgate behaves as expected in a variety of scenarios, mimicking MySQL's behavior as closely as possible. @@ -76,6 +84,8 @@ Usage of ./vitess-tester: logs at or above this threshold go to stderr (default 2) -topo-flavor string choose a topo server from etcd2, zk2 or consul (default "etcd2") + -trace string + Do a vexplain trace on all queries and store the output in the given file. -v value log level for V logs -vmodule value diff --git a/src/cmd/vtbenchstat/vtbenchstat.go b/src/cmd/vtbenchstat/vtbenchstat.go index faf3443..41913ef 100644 --- a/src/cmd/vtbenchstat/vtbenchstat.go +++ b/src/cmd/vtbenchstat/vtbenchstat.go @@ -44,6 +44,7 @@ type ( NoOfCalls int `json:"NoOfCalls"` AvgNumberOfRows float64 `json:"AvgNumberOfRows"` MedianNumberOfRows float64 `json:"MedianNumberOfRows"` + ShardsQueried int `json:"ShardsQueried"` Inputs []Trace `json:"Inputs,omitempty"` } @@ -51,7 +52,8 @@ type ( Q TracedQuery RouteCalls, RowsSent, - RowsInMemory int + RowsInMemory, + ShardsQueried int } TraceFile struct { @@ -85,6 +87,7 @@ func summarizeTrace(t TracedQuery) QuerySummary { } visit(t.Trace, func(trace Trace) { + summary.ShardsQueried += trace.ShardsQueried switch trace.OperatorType { case "Route": summary.RouteCalls += trace.NoOfCalls @@ -104,11 +107,16 @@ func summarizeTrace(t TracedQuery) QuerySummary { return summary } +func exit(msg string) { + fmt.Println(msg) + os.Exit(1) +} + func readTraceFile(fileName string) TraceFile { // Open the JSON file file, err := os.Open(fileName) if err != nil { - panic(err.Error()) + exit("Error opening file: " + err.Error()) } defer file.Close() @@ -118,7 +126,7 @@ func readTraceFile(fileName string) TraceFile { // Read the opening bracket _, err = decoder.Token() if err != nil { - panic(err.Error()) + exit("Error reading json: " + err.Error()) } // Read the file contents @@ -127,7 +135,7 @@ func readTraceFile(fileName string) TraceFile { var element TracedQuery err := decoder.Decode(&element) if err != nil { - panic(err.Error()) + exit("Error reading json: " + err.Error()) } queries = append(queries, element) } @@ -135,7 +143,7 @@ func readTraceFile(fileName string) TraceFile { // Read the closing bracket _, err = decoder.Token() if err != nil { - panic(err.Error()) + exit("Error reading json: " + err.Error()) } sort.Slice(queries, func(i, j int) bool { @@ -180,23 +188,37 @@ func printSummary(file TraceFile) { } for _, query := range file.Queries { querySummary := summary[query.Query] - printQuery(query, termWidth) + printQuery(query, termWidth, false) table := tablewriter.NewWriter(os.Stdout) table.SetAutoFormatHeaders(false) - table.SetHeader([]string{"Route Calls", "Rows Sent", "Rows In Memory"}) - table.Append([]string{strconv.Itoa(querySummary.RouteCalls), strconv.Itoa(querySummary.RowsSent), strconv.Itoa(querySummary.RowsInMemory)}) + table.SetHeader([]string{ + "Route Calls", + "Rows Sent", + "Rows In Memory", + "Shards Queried", + }) + table.Append([]string{ + strconv.Itoa(querySummary.RouteCalls), + strconv.Itoa(querySummary.RowsSent), + strconv.Itoa(querySummary.RowsInMemory), + strconv.Itoa(querySummary.ShardsQueried), + }) table.Render() fmt.Println() } } -func printQuery(q TracedQuery, terminalWidth int) { +func printQuery(q TracedQuery, terminalWidth int, significant bool) { fmt.Printf("%s", queryPrefix) err := quick.Highlight(os.Stdout, limitQueryLength(q.Query, terminalWidth), "sql", "terminal", "monokai") if err != nil { return } - fmt.Printf("\nLine # %s\n", q.LineNumber) + improved := "" + if significant { + improved = " (significant)" + } + fmt.Printf("\nLine # %s%s\n", q.LineNumber, improved) } const significantChangeThreshold = 10 @@ -211,7 +233,8 @@ func compareTraces(file1, file2 TraceFile) { } var significantChanges, totalQueries int - var totalRouteCallsChange, totalDataSentChange, totalMemoryRowsChange float64 + var s1RouteCalls, s1DataSent, s1MemoryRows, s1ShardsQueried int + var s2RouteCalls, s2DataSent, s2MemoryRows, s2ShardsQueried int for query, s1 := range summary1 { s2, ok := summary2[query] @@ -220,43 +243,51 @@ func compareTraces(file1, file2 TraceFile) { } totalQueries++ - printQuery(s1.Q, termWidth) table := tablewriter.NewWriter(os.Stdout) table.SetHeader([]string{"Metric", file1.Name, file2.Name, "Diff", "% Change"}) table.SetAutoFormatHeaders(false) - routeCallsChange := compareMetric(table, "Route Calls", s1.RouteCalls, s2.RouteCalls) - if !math.IsNaN(routeCallsChange) { - totalRouteCallsChange += routeCallsChange - } - - dataSentChange := compareMetric(table, "Rows Sent", s1.RowsSent, s2.RowsSent) - if !math.IsNaN(dataSentChange) { - totalDataSentChange += dataSentChange - } - - memoryRowsChange := compareMetric(table, "Rows In Memory", s1.RowsInMemory, s2.RowsInMemory) - if !math.IsNaN(memoryRowsChange) { - totalMemoryRowsChange += memoryRowsChange - } + m1 := compareMetric(table, "Route Calls", s1.RouteCalls, s2.RouteCalls) + m2 := compareMetric(table, "Rows Sent", s1.RowsSent, s2.RowsSent) + m3 := compareMetric(table, "Rows In Memory", s1.RowsInMemory, s2.RowsInMemory) + m4 := compareMetric(table, "Shards Queried", s1.ShardsQueried, s2.ShardsQueried) - if math.Abs(routeCallsChange) > significantChangeThreshold || math.Abs(dataSentChange) > significantChangeThreshold { + // we introduce variables to make sure we don't shortcut the evaluation + significant := m1 || m2 || m3 || m4 + if significant { significantChanges++ } + s1RouteCalls += s1.RouteCalls + s1DataSent += s1.RowsSent + s1MemoryRows += s1.RowsInMemory + s1ShardsQueried += s1.ShardsQueried + s2RouteCalls += s2.RouteCalls + s2DataSent += s2.RowsSent + s2MemoryRows += s2.RowsInMemory + s2ShardsQueried += s2.ShardsQueried + + printQuery(s1.Q, termWidth, significant) table.Render() fmt.Println() } + totalRouteCallsChange := float64(s2RouteCalls-s1RouteCalls) / float64(s1RouteCalls) * 100 + totalDataSentChange := float64(s2DataSent-s1DataSent) / float64(s1DataSent) * 100 + totalMemoryRowsChange := float64(s2MemoryRows-s1MemoryRows) / float64(s1MemoryRows) * 100 + totalShardsQueriedChange := float64(s2ShardsQueried-s1ShardsQueried) / float64(s1ShardsQueried) * 100 + // Print summary fmt.Println("Summary:") fmt.Printf("- %d out of %d queries showed significant change\n", significantChanges, totalQueries) - fmt.Printf("- Average change in Route Calls: %.2f%%\n", totalRouteCallsChange/float64(totalQueries)) - fmt.Printf("- Average change in Data Sent: %.2f%%\n", totalDataSentChange/float64(totalQueries)) - fmt.Printf("- Average change in Rows In Memory: %.2f%%\n", totalMemoryRowsChange/float64(totalQueries)) + fmt.Printf("- Average change in Route Calls: %.2f%%\n", totalRouteCallsChange) + fmt.Printf("- Average change in Data Sent: %.2f%%\n", totalDataSentChange) + fmt.Printf("- Average change in Rows In Memory: %.2f%%\n", totalMemoryRowsChange) + fmt.Printf("- Average change in Shards Queried: %.2f%%\n", totalShardsQueriedChange) } -func compareMetric(table *tablewriter.Table, metricName string, val1, val2 int) float64 { +// compareMetric compares two metrics and appends the result to the table, returning true if the change is significant +func compareMetric(table *tablewriter.Table, metricName string, val1, val2 int) bool { diff := val2 - val1 percentChange := float64(diff) / float64(val1) * 100 percentChangeStr := fmt.Sprintf("%.2f%%", percentChange) @@ -273,5 +304,5 @@ func compareMetric(table *tablewriter.Table, metricName string, val1, val2 int) percentChangeStr, }) - return percentChange + return percentChange < -significantChangeThreshold } From 584a1c6d7ed2010dcb7d7210f026abac38164e7f Mon Sep 17 00:00:00 2001 From: Andres Taylor Date: Thu, 19 Sep 2024 14:21:11 +0200 Subject: [PATCH 3/5] update trace & README Signed-off-by: Andres Taylor --- README.md | 25 ++++ src/cmd/vtbenchstat/trace-log.json | 194 +++++++++++++++-------------- 2 files changed, 126 insertions(+), 93 deletions(-) diff --git a/README.md b/README.md index 78541ac..78b879b 100644 --- a/README.md +++ b/README.md @@ -110,6 +110,31 @@ vitess-tester -vtexplain-vschema t/vtexplain-vschema.json t/vtexplain.test # run The test files can be amended with directives to control the testing process. Check out `directives.test` to see examples of what directives are available. +## Tracing and comparing execution plans + +`vitess-tester` can run in tracing mode. When it does, it will not only run the tests but also generate a trace of the query execution plan. +The trace is created using `vexplain trace`, a tool that provides detailed information about how a query is executed. + +To run `vitess-tester` in tracing mode, use the `-trace` flag: + +```bash +vitess-tester --sharded -trace=trace-log.json t/tpch.test +``` + +This will create a trace log, which you can then either summarize using `vtbenchstat` or compare with another trace log. + +Running `vtbenchstat` will provide a summary of the trace log, including the number of queries, the number of rows returned, and the time taken to execute the queries. + +```bash +vtbenchstat trace-log.json +``` + +To compare two trace logs, use the `vtbenchstat` command with two trace logs as arguments: + +```bash +vtbenchstat trace-log1.json trace-log2.json +``` + ## Contributing Contributions are welcomed and greatly appreciated. You can help by: diff --git a/src/cmd/vtbenchstat/trace-log.json b/src/cmd/vtbenchstat/trace-log.json index 705890b..5ce0bdb 100644 --- a/src/cmd/vtbenchstat/trace-log.json +++ b/src/cmd/vtbenchstat/trace-log.json @@ -10,9 +10,10 @@ "Sharded": true }, "TargetTabletType": "PRIMARY", - "NoOfCalls": 2, + "NoOfCalls": 1, "AvgNumberOfRows": 0, "MedianNumberOfRows": 0, + "ShardsQueried": 1, "Query": "insert into region(R_REGIONKEY, R_NAME, R_COMMENT) values (:_R_REGIONKEY_0, 'ASIA', 'Eastern Asia'), (:_R_REGIONKEY_1, 'MIDDLE EAST', 'Rich cultural heritage')", "TableName": "region", "VindexValues": { @@ -31,9 +32,10 @@ "Sharded": true }, "TargetTabletType": "PRIMARY", - "NoOfCalls": 2, + "NoOfCalls": 1, "AvgNumberOfRows": 0, "MedianNumberOfRows": 0, + "ShardsQueried": 1, "Query": "insert into nation(N_NATIONKEY, N_NAME, N_REGIONKEY, N_COMMENT) values (:_N_NATIONKEY_0, 'China', 1, 'Large population'), (:_N_NATIONKEY_1, 'India', 1, 'Large variety of cultures'), (:_N_NATIONKEY_2, 'Nation A', 2, 'Historic sites'), (:_N_NATIONKEY_3, 'Nation B', 2, 'Beautiful landscapes')", "TableName": "nation", "VindexValues": { @@ -52,9 +54,10 @@ "Sharded": true }, "TargetTabletType": "PRIMARY", - "NoOfCalls": 2, + "NoOfCalls": 1, "AvgNumberOfRows": 0, "MedianNumberOfRows": 0, + "ShardsQueried": 1, "Query": "insert into supplier(S_SUPPKEY, S_NAME, S_ADDRESS, S_NATIONKEY, S_PHONE, S_ACCTBAL, S_COMMENT) values (:_S_SUPPKEY_0, 'Supplier A', '123 Square', 1, '86-123-4567', 5000.00, 'High quality steel'), (:_S_SUPPKEY_1, 'Supplier B', '456 Ganges St', 2, '91-789-4561', 5500.00, 'Efficient production'), (:_S_SUPPKEY_2, 'Supplier 1', 'Supplier Address 1', 3, '91-789-4562', 3000.00, 'Supplier Comment 1'), (:_S_SUPPKEY_3, 'Supplier 2', 'Supplier Address 2', 2, '91-789-4563', 4000.00, 'Supplier Comment 2')", "TableName": "supplier", "VindexValues": { @@ -73,9 +76,10 @@ "Sharded": true }, "TargetTabletType": "PRIMARY", - "NoOfCalls": 2, + "NoOfCalls": 1, "AvgNumberOfRows": 0, "MedianNumberOfRows": 0, + "ShardsQueried": 1, "Query": "insert into part(P_PARTKEY, P_NAME, P_MFGR, P_BRAND, P_TYPE, P_SIZE, P_CONTAINER, P_RETAILPRICE, P_COMMENT) values (:_P_PARTKEY_0, 'Part 100', 'MFGR A', 'Brand X', 'BOLT STEEL', 30, 'SM BOX', 45.00, 'High strength'), (:_P_PARTKEY_1, 'Part 101', 'MFGR B', 'Brand Y', 'NUT STEEL', 30, 'LG BOX', 30.00, 'Rust resistant')", "TableName": "part", "VindexValues": { @@ -94,9 +98,10 @@ "Sharded": true }, "TargetTabletType": "PRIMARY", - "NoOfCalls": 2, + "NoOfCalls": 1, "AvgNumberOfRows": 0, "MedianNumberOfRows": 0, + "ShardsQueried": 1, "Query": "insert into partsupp(PS_PARTKEY, PS_SUPPKEY, PS_AVAILQTY, PS_SUPPLYCOST, PS_COMMENT) values (:_PS_PARTKEY_0, :_PS_SUPPKEY_0, 500, 10.00, 'Deliveries on time'), (:_PS_PARTKEY_1, :_PS_SUPPKEY_1, 300, 9.00, 'Back orders possible'), (:_PS_PARTKEY_2, :_PS_SUPPKEY_2, 600, 8.50, 'Bulk discounts available')", "TableName": "partsupp", "VindexValues": { @@ -115,9 +120,10 @@ "Sharded": true }, "TargetTabletType": "PRIMARY", - "NoOfCalls": 2, + "NoOfCalls": 1, "AvgNumberOfRows": 0, "MedianNumberOfRows": 0, + "ShardsQueried": 1, "Query": "insert into customer(C_CUSTKEY, C_NAME, C_ADDRESS, C_NATIONKEY, C_PHONE, C_ACCTBAL, C_MKTSEGMENT, C_COMMENT) values (:_C_CUSTKEY_0, 'Customer A', '1234 Drive Lane', 1, '123-456-7890', 1000.00, 'AUTOMOBILE', 'Frequent orders'), (:_C_CUSTKEY_1, 'Customer B', '5678 Park Ave', 2, '234-567-8901', 2000.00, 'AUTOMOBILE', 'Large orders'), (:_C_CUSTKEY_2, 'Customer 1', 'Address 1', 1, 'Phone 1', 1000.00, 'Segment 1', 'Comment 1'), (:_C_CUSTKEY_3, 'Customer 2', 'Address 2', 2, 'Phone 2', 2000.00, 'Segment 2', 'Comment 2')", "TableName": "customer", "VindexValues": { @@ -136,9 +142,10 @@ "Sharded": true }, "TargetTabletType": "PRIMARY", - "NoOfCalls": 2, + "NoOfCalls": 1, "AvgNumberOfRows": 0, "MedianNumberOfRows": 0, + "ShardsQueried": 2, "Query": "insert into orders(O_ORDERKEY, O_CUSTKEY, O_ORDERSTATUS, O_TOTALPRICE, O_ORDERDATE, O_ORDERPRIORITY, O_CLERK, O_SHIPPRIORITY, O_COMMENT) values (:_O_ORDERKEY_0, 1, 'O', 15000.00, '1995-03-10', '1-URGENT', 'Clerk#0001', 1, 'N/A'), (:_O_ORDERKEY_1, 2, 'O', 25000.00, '1995-03-05', '2-HIGH', 'Clerk#0002', 2, 'N/A'), (:_O_ORDERKEY_2, 3, 'O', 10000.00, '1994-01-10', 'Priority 1', 'Clerk 1', 1, 'Order Comment 1'), (:_O_ORDERKEY_3, 4, 'O', 20000.00, '1994-06-15', 'Priority 2', 'Clerk 2', 1, 'Order Comment 2')", "TableName": "orders", "VindexValues": { @@ -157,9 +164,10 @@ "Sharded": true }, "TargetTabletType": "PRIMARY", - "NoOfCalls": 2, + "NoOfCalls": 1, "AvgNumberOfRows": 0, "MedianNumberOfRows": 0, + "ShardsQueried": 2, "Query": "insert into lineitem(L_ORDERKEY, L_PARTKEY, L_SUPPKEY, L_LINENUMBER, L_QUANTITY, L_EXTENDEDPRICE, L_DISCOUNT, L_TAX, L_RETURNFLAG, L_LINESTATUS, L_SHIPDATE, L_COMMITDATE, L_RECEIPTDATE, L_SHIPINSTRUCT, L_SHIPMODE, L_COMMENT) values (:_L_ORDERKEY_0, 200, 300, :_L_LINENUMBER_0, 10, 5000.00, 0.05, 0.10, 'N', 'O', '1995-03-15', '1995-03-14', '1995-03-16', 'DELIVER IN PERSON', 'TRUCK', 'Urgent delivery'), (:_L_ORDERKEY_1, 201, 301, :_L_LINENUMBER_1, 20, 10000.00, 0.10, 0.10, 'R', 'F', '1995-03-17', '1995-03-15', '1995-03-18', 'NONE', 'MAIL', 'Handle with care'), (:_L_ORDERKEY_2, 202, 302, :_L_LINENUMBER_2, 30, 15000.00, 0.00, 0.10, 'A', 'F', '1995-03-20', '1995-03-18', '1995-03-21', 'TAKE BACK RETURN', 'SHIP', 'Standard delivery'), (:_L_ORDERKEY_3, 203, 303, :_L_LINENUMBER_3, 40, 10000.00, 0.20, 0.10, 'N', 'O', '1995-03-22', '1995-03-20', '1995-03-23', 'DELIVER IN PERSON', 'RAIL', 'Expedite'), (:_L_ORDERKEY_4, 101, 1, :_L_LINENUMBER_4, 5, 5000.00, 0.1, 0.05, 'N', 'O', '1994-01-12', '1994-01-11', '1994-01-13', 'Deliver in person', 'TRUCK', 'Lineitem Comment 1'), (:_L_ORDERKEY_5, 102, 2, :_L_LINENUMBER_5, 3, 15000.00, 0.2, 0.05, 'R', 'F', '1994-06-17', '1994-06-15', '1994-06-18', 'Leave at front door', 'AIR', 'Lineitem Comment 2'), (:_L_ORDERKEY_6, 100, 2, :_L_LINENUMBER_6, 30, 10000.00, 0.05, 0.07, 'A', 'F', '1998-07-21', '1998-07-22', '1998-07-23', 'DELIVER IN PERSON', 'TRUCK', 'N/A'), (:_L_ORDERKEY_7, 101, 3, :_L_LINENUMBER_7, 50, 15000.00, 0.10, 0.08, 'N', 'O', '1998-08-10', '1998-08-11', '1998-08-12', 'NONE', 'AIR', 'N/A'), (:_L_ORDERKEY_8, 102, 4, :_L_LINENUMBER_8, 70, 21000.00, 0.02, 0.04, 'R', 'F', '1998-06-30', '1998-07-01', '1998-07-02', 'TAKE BACK RETURN', 'MAIL', 'N/A'), (:_L_ORDERKEY_9, 103, 5, :_L_LINENUMBER_9, 90, 30000.00, 0.15, 0.10, 'A', 'O', '1998-05-15', '1998-05-16', '1998-05-17', 'DELIVER IN PERSON', 'RAIL', 'N/A'), (:_L_ORDERKEY_10, 104, 2, :_L_LINENUMBER_10, 45, 45000.00, 0.20, 0.15, 'N', 'F', '1998-07-15', '1998-07-16', '1998-07-17', 'NONE', 'SHIP', 'N/A')", "TableName": "lineitem", "VindexValues": { @@ -204,9 +212,10 @@ "Name": "mysqltest", "Sharded": true }, - "NoOfCalls": 2, + "NoOfCalls": 1, "AvgNumberOfRows": 8, "MedianNumberOfRows": 8, + "ShardsQueried": 2, "FieldQuery": "select l_returnflag, l_linestatus, sum(l_quantity) as sum_qty, sum(l_extendedprice) as sum_base_price, sum(l_extendedprice * (1 - l_discount)) as sum_disc_price, sum(l_extendedprice * (1 - l_discount) * (1 + l_tax)) as sum_charge, sum(l_quantity) as avg_qty, sum(l_extendedprice) as avg_price, sum(l_discount) as avg_disc, count(*) as count_order, count(l_quantity), count(l_extendedprice), count(l_discount) from lineitem where 1 != 1 group by l_returnflag, l_linestatus", "OrderBy": "0 ASC COLLATE utf8mb4_0900_ai_ci, 1 ASC COLLATE utf8mb4_0900_ai_ci", "Query": "select l_returnflag, l_linestatus, sum(l_quantity) as sum_qty, sum(l_extendedprice) as sum_base_price, sum(l_extendedprice * (1 - l_discount)) as sum_disc_price, sum(l_extendedprice * (1 - l_discount) * (1 + l_tax)) as sum_charge, sum(l_quantity) as avg_qty, sum(l_extendedprice) as avg_price, sum(l_discount) as avg_disc, count(*) as count_order, count(l_quantity), count(l_extendedprice), count(l_discount) from lineitem where l_shipdate \u003c= date_sub('1998-12-01', interval 108 day) group by l_returnflag, l_linestatus order by lineitem.l_returnflag asc, lineitem.l_linestatus asc", @@ -275,9 +284,10 @@ "Name": "mysqltest", "Sharded": true }, - "NoOfCalls": 2, + "NoOfCalls": 1, "AvgNumberOfRows": 2, "MedianNumberOfRows": 2, + "ShardsQueried": 2, "FieldQuery": "select sum(l_extendedprice * (1 - l_discount)) as revenue, l_orderkey, o_orderdate, o_shippriority, o_custkey from orders, lineitem where 1 != 1 group by l_orderkey, o_orderdate, o_shippriority, o_custkey", "OrderBy": "1 ASC, 2 ASC, 3 ASC", "Query": "select sum(l_extendedprice * (1 - l_discount)) as revenue, l_orderkey, o_orderdate, o_shippriority, o_custkey from orders, lineitem where o_orderdate \u003c '1995-03-13' and l_shipdate \u003e '1995-03-13' and l_orderkey = o_orderkey group by l_orderkey, o_orderdate, o_shippriority, o_custkey order by l_orderkey asc, o_orderdate asc, o_shippriority asc", @@ -290,9 +300,10 @@ "Name": "mysqltest", "Sharded": true }, - "NoOfCalls": 4, + "NoOfCalls": 2, "AvgNumberOfRows": 1, "MedianNumberOfRows": 1, + "ShardsQueried": 2, "FieldQuery": "select count(*) from customer where 1 != 1 group by .0", "Query": "select count(*) from customer where c_mktsegment = 'AUTOMOBILE' and c_custkey = :o_custkey /* INT32 */ group by .0", "Table": "customer", @@ -331,9 +342,10 @@ "Name": "mysqltest", "Sharded": true }, - "NoOfCalls": 2, + "NoOfCalls": 1, "AvgNumberOfRows": 2, "MedianNumberOfRows": 2, + "ShardsQueried": 2, "FieldQuery": "select o_orderpriority, count(*) as order_count from orders where 1 != 1 group by o_orderpriority", "OrderBy": "0 ASC COLLATE utf8mb4_0900_ai_ci", "Query": "select o_orderpriority, count(*) as order_count from orders where o_orderdate \u003e= '1995-01-01' and o_orderdate \u003c date_add('1995-01-01', interval '3' month) and exists (select 1 from lineitem where l_orderkey = o_orderkey and l_commitdate \u003c l_receiptdate) group by o_orderpriority order by orders.o_orderpriority asc", @@ -423,9 +435,10 @@ "Name": "mysqltest", "Sharded": true }, - "NoOfCalls": 2, + "NoOfCalls": 1, "AvgNumberOfRows": 2, "MedianNumberOfRows": 2, + "ShardsQueried": 2, "FieldQuery": "select sum(l_extendedprice * (1 - l_discount)) as revenue, l_suppkey, o_custkey from orders, lineitem where 1 != 1 group by l_suppkey, o_custkey", "Query": "select sum(l_extendedprice * (1 - l_discount)) as revenue, l_suppkey, o_custkey from orders, lineitem where o_orderdate \u003e= '1994-01-01' and o_orderdate \u003c date_add('1994-01-01', interval '1' year) and l_orderkey = o_orderkey group by l_suppkey, o_custkey", "Table": "lineitem, orders" @@ -437,9 +450,10 @@ "Name": "mysqltest", "Sharded": true }, - "NoOfCalls": 4, + "NoOfCalls": 2, "AvgNumberOfRows": 1, "MedianNumberOfRows": 1, + "ShardsQueried": 2, "FieldQuery": "select count(*), c_nationkey from customer where 1 != 1 group by c_nationkey", "Query": "select count(*), c_nationkey from customer where c_custkey = :o_custkey /* INT32 */ group by c_nationkey", "Table": "customer", @@ -504,9 +518,10 @@ "Name": "mysqltest", "Sharded": true }, - "NoOfCalls": 4, + "NoOfCalls": 2, "AvgNumberOfRows": 1, "MedianNumberOfRows": 1, + "ShardsQueried": 2, "FieldQuery": "select count(*), s_nationkey from supplier where 1 != 1 group by s_nationkey", "Query": "select count(*), s_nationkey from supplier where s_nationkey = :c_nationkey /* INT32 */ and s_suppkey = :l_suppkey /* INT32 */ group by s_nationkey", "Table": "supplier", @@ -522,9 +537,10 @@ "Name": "mysqltest", "Sharded": true }, - "NoOfCalls": 4, + "NoOfCalls": 2, "AvgNumberOfRows": 1, "MedianNumberOfRows": 1, + "ShardsQueried": 2, "FieldQuery": "select count(*), n_name, n_regionkey from nation where 1 != 1 group by n_name, n_regionkey", "Query": "select count(*), n_name, n_regionkey from nation where n_nationkey = :s_nationkey /* INT32 */ group by n_name, n_regionkey", "Table": "nation", @@ -544,9 +560,10 @@ "Name": "mysqltest", "Sharded": true }, - "NoOfCalls": 4, + "NoOfCalls": 2, "AvgNumberOfRows": 0, "MedianNumberOfRows": 0, + "ShardsQueried": 2, "FieldQuery": "select count(*) from region where 1 != 1 group by .0", "Query": "select count(*) from region where r_name = 'MIDDLE EAST' and r_regionkey = :n_regionkey /* INT32 */ group by .0", "Table": "region", @@ -588,9 +605,10 @@ "Name": "mysqltest", "Sharded": true }, - "NoOfCalls": 2, + "NoOfCalls": 1, "AvgNumberOfRows": 2, "MedianNumberOfRows": 2, + "ShardsQueried": 2, "FieldQuery": "select sum(l_extendedprice * l_discount) as revenue from lineitem where 1 != 1", "Query": "select sum(l_extendedprice * l_discount) as revenue from lineitem where l_shipdate \u003e= '1994-01-01' and l_shipdate \u003c date_add('1994-01-01', interval '1' year) and l_discount between 0.06 - 0.01 and 0.06 + 0.01 and l_quantity \u003c 24", "Table": "lineitem" @@ -677,9 +695,10 @@ "Name": "mysqltest", "Sharded": true }, - "NoOfCalls": 2, + "NoOfCalls": 1, "AvgNumberOfRows": 4, "MedianNumberOfRows": 4, + "ShardsQueried": 2, "FieldQuery": "select sum(volume) as revenue, l_year, shipping.o_custkey, shipping.l_suppkey, weight_string(l_year) from (select extract(year from l_shipdate) as l_year, l_extendedprice * (1 - l_discount) as volume, o_custkey as o_custkey, l_suppkey as l_suppkey from lineitem, orders where 1 != 1) as shipping where 1 != 1 group by l_year, shipping.o_custkey, shipping.l_suppkey, weight_string(l_year)", "Query": "select sum(volume) as revenue, l_year, shipping.o_custkey, shipping.l_suppkey, weight_string(l_year) from (select extract(year from l_shipdate) as l_year, l_extendedprice * (1 - l_discount) as volume, o_custkey as o_custkey, l_suppkey as l_suppkey from lineitem, orders where l_shipdate between '1995-01-01' and '1996-12-31' and o_orderkey = l_orderkey) as shipping group by l_year, shipping.o_custkey, shipping.l_suppkey, weight_string(l_year)", "Table": "lineitem, orders" @@ -713,9 +732,10 @@ "Name": "mysqltest", "Sharded": true }, - "NoOfCalls": 8, + "NoOfCalls": 4, "AvgNumberOfRows": 0, "MedianNumberOfRows": 0, + "ShardsQueried": 4, "FieldQuery": "select count(*), shipping.s_nationkey from (select s_nationkey as s_nationkey from supplier where 1 != 1) as shipping where 1 != 1 group by shipping.s_nationkey", "Query": "select count(*), shipping.s_nationkey from (select s_nationkey as s_nationkey from supplier where s_suppkey = :l_suppkey /* INT32 */) as shipping group by shipping.s_nationkey", "Table": "supplier", @@ -731,9 +751,7 @@ "Name": "mysqltest", "Sharded": true }, - "NoOfCalls": 1, - "AvgNumberOfRows": 0, - "MedianNumberOfRows": 0, + "ShardsQueried": 1, "FieldQuery": "select count(*), supp_nation from (select n1.n_name as supp_nation from nation as n1 where 1 != 1) as shipping where 1 != 1 group by supp_nation", "Query": "select count(*), supp_nation from (select n1.n_name as supp_nation from nation as n1 where n1.n_nationkey = :s_nationkey /* INT32 */) as shipping group by supp_nation", "Table": "nation", @@ -773,9 +791,7 @@ "Name": "mysqltest", "Sharded": true }, - "NoOfCalls": 1, - "AvgNumberOfRows": 0, - "MedianNumberOfRows": 0, + "ShardsQueried": 1, "FieldQuery": "select count(*), shipping.c_nationkey from (select c_nationkey as c_nationkey from customer where 1 != 1) as shipping where 1 != 1 group by shipping.c_nationkey", "Query": "select count(*), shipping.c_nationkey from (select c_nationkey as c_nationkey from customer where c_custkey = :o_custkey /* INT32 */) as shipping group by shipping.c_nationkey", "Table": "customer", @@ -791,9 +807,7 @@ "Name": "mysqltest", "Sharded": true }, - "NoOfCalls": 1, - "AvgNumberOfRows": 0, - "MedianNumberOfRows": 0, + "ShardsQueried": 1, "FieldQuery": "select count(*), cust_nation from (select n2.n_name as cust_nation from nation as n2 where 1 != 1) as shipping where 1 != 1 group by cust_nation", "Query": "select count(*), cust_nation from (select n2.n_name as cust_nation from nation as n2 where (:n1_n_name /* CHAR(25) */ = 'JAPAN' and n2.n_name = 'INDIA' or :n1_n_name /* CHAR(25) */ = 'INDIA' and n2.n_name = 'JAPAN') and n2.n_nationkey = :c_nationkey /* INT32 */) as shipping group by cust_nation", "Table": "nation", @@ -902,9 +916,10 @@ "Name": "mysqltest", "Sharded": true }, - "NoOfCalls": 2, + "NoOfCalls": 1, "AvgNumberOfRows": 4, "MedianNumberOfRows": 4, + "ShardsQueried": 2, "FieldQuery": "select all_nations.o_year, all_nations.volume, all_nations.o_custkey, all_nations.l_suppkey, all_nations.l_partkey, weight_string(all_nations.o_year) from (select extract(year from o_orderdate) as o_year, l_extendedprice * (1 - l_discount) as volume, o_custkey as o_custkey, l_suppkey as l_suppkey, l_partkey as l_partkey from lineitem, orders where 1 != 1) as all_nations where 1 != 1", "OrderBy": "(0|5) ASC, 2 ASC", "Query": "select all_nations.o_year, all_nations.volume, all_nations.o_custkey, all_nations.l_suppkey, all_nations.l_partkey, weight_string(all_nations.o_year) from (select extract(year from o_orderdate) as o_year, l_extendedprice * (1 - l_discount) as volume, o_custkey as o_custkey, l_suppkey as l_suppkey, l_partkey as l_partkey from lineitem, orders where o_orderdate between '1995-01-01' and '1996-12-31' and l_orderkey = o_orderkey) as all_nations order by all_nations.o_year asc, all_nations.o_custkey asc", @@ -917,9 +932,10 @@ "Name": "mysqltest", "Sharded": true }, - "NoOfCalls": 8, + "NoOfCalls": 4, "AvgNumberOfRows": 0, "MedianNumberOfRows": 0, + "ShardsQueried": 4, "FieldQuery": "select 1 from part where 1 != 1", "Query": "select 1 from part where p_type = 'SMALL PLATED COPPER' and p_partkey = :l_partkey /* INT32 */", "Table": "part", @@ -946,9 +962,7 @@ "Name": "mysqltest", "Sharded": true }, - "NoOfCalls": 1, - "AvgNumberOfRows": 0, - "MedianNumberOfRows": 0, + "ShardsQueried": 1, "FieldQuery": "select all_nations.s_nationkey from (select s_nationkey as s_nationkey from supplier where 1 != 1) as all_nations where 1 != 1", "Query": "select all_nations.s_nationkey from (select s_nationkey as s_nationkey from supplier where s_suppkey = :l_suppkey /* INT32 */) as all_nations", "Table": "supplier", @@ -964,9 +978,7 @@ "Name": "mysqltest", "Sharded": true }, - "NoOfCalls": 1, - "AvgNumberOfRows": 0, - "MedianNumberOfRows": 0, + "ShardsQueried": 1, "FieldQuery": "select all_nations.nation, case when nation = 'INDIA' then :volume else 0 end from (select n2.n_name as nation from nation as n2 where 1 != 1) as all_nations where 1 != 1", "Query": "select all_nations.nation, case when nation = 'INDIA' then :volume else 0 end from (select n2.n_name as nation from nation as n2 where n2.n_nationkey = :s_nationkey /* INT32 */) as all_nations", "Table": "nation", @@ -1019,9 +1031,7 @@ "Name": "mysqltest", "Sharded": true }, - "NoOfCalls": 1, - "AvgNumberOfRows": 0, - "MedianNumberOfRows": 0, + "ShardsQueried": 1, "FieldQuery": "select count(*), c_nationkey from customer where 1 != 1 group by c_nationkey", "Query": "select count(*), c_nationkey from customer where c_custkey = :o_custkey /* INT32 */ group by c_nationkey", "Table": "customer", @@ -1037,9 +1047,7 @@ "Name": "mysqltest", "Sharded": true }, - "NoOfCalls": 1, - "AvgNumberOfRows": 0, - "MedianNumberOfRows": 0, + "ShardsQueried": 1, "FieldQuery": "select count(*), n1.n_regionkey from nation as n1 where 1 != 1 group by n1.n_regionkey", "Query": "select count(*), n1.n_regionkey from nation as n1 where n1.n_nationkey = :c_nationkey /* INT32 */ group by n1.n_regionkey", "Table": "nation", @@ -1059,9 +1067,7 @@ "Name": "mysqltest", "Sharded": true }, - "NoOfCalls": 1, - "AvgNumberOfRows": 0, - "MedianNumberOfRows": 0, + "ShardsQueried": 1, "FieldQuery": "select count(*) from region where 1 != 1 group by .0", "Query": "select count(*) from region where r_name = 'ASIA' and r_regionkey = :n1_n_regionkey /* INT32 */ group by .0", "Table": "region", @@ -1172,9 +1178,10 @@ "Name": "mysqltest", "Sharded": true }, - "NoOfCalls": 2, + "NoOfCalls": 1, "AvgNumberOfRows": 6, "MedianNumberOfRows": 6, + "ShardsQueried": 2, "FieldQuery": "select profit.o_year, profit.l_extendedprice, profit.l_discount, profit.l_quantity, profit.l_suppkey, profit.l_partkey, weight_string(profit.o_year) from (select extract(year from o_orderdate) as o_year, l_extendedprice, l_discount, l_quantity, l_suppkey as l_suppkey, l_partkey as l_partkey from lineitem, orders where 1 != 1) as profit where 1 != 1", "OrderBy": "(0|6) ASC, 4 ASC", "Query": "select profit.o_year, profit.l_extendedprice, profit.l_discount, profit.l_quantity, profit.l_suppkey, profit.l_partkey, weight_string(profit.o_year) from (select extract(year from o_orderdate) as o_year, l_extendedprice, l_discount, l_quantity, l_suppkey as l_suppkey, l_partkey as l_partkey from lineitem, orders where o_orderkey = l_orderkey) as profit order by o_year asc, profit.l_suppkey asc", @@ -1187,9 +1194,10 @@ "Name": "mysqltest", "Sharded": true }, - "NoOfCalls": 12, + "NoOfCalls": 6, "AvgNumberOfRows": 0, "MedianNumberOfRows": 0, + "ShardsQueried": 6, "FieldQuery": "select 1 from part where 1 != 1", "Query": "select 1 from part where p_name like '%dim%' and p_partkey = :l_partkey /* INT32 */", "Table": "part", @@ -1207,9 +1215,7 @@ "Name": "mysqltest", "Sharded": true }, - "NoOfCalls": 1, - "AvgNumberOfRows": 0, - "MedianNumberOfRows": 0, + "ShardsQueried": 1, "FieldQuery": "select profit.amount from (select :l_extendedprice /* DECIMAL(15,2) */ * (1 - :l_discount /* DECIMAL(15,2) */) - ps_supplycost * :l_quantity /* DECIMAL(15,2) */ as amount from partsupp where 1 != 1) as profit where 1 != 1", "Query": "select profit.amount from (select :l_extendedprice /* DECIMAL(15,2) */ * (1 - :l_discount /* DECIMAL(15,2) */) - ps_supplycost * :l_quantity /* DECIMAL(15,2) */ as amount from partsupp where ps_partkey = :l_partkey /* INT32 */ and ps_suppkey = :l_suppkey /* INT32 */) as profit", "Table": "partsupp", @@ -1245,9 +1251,7 @@ "Name": "mysqltest", "Sharded": true }, - "NoOfCalls": 1, - "AvgNumberOfRows": 0, - "MedianNumberOfRows": 0, + "ShardsQueried": 1, "FieldQuery": "select count(*), profit.s_nationkey from (select s_nationkey as s_nationkey from supplier where 1 != 1) as profit where 1 != 1 group by profit.s_nationkey", "Query": "select count(*), profit.s_nationkey from (select s_nationkey as s_nationkey from supplier where s_suppkey = :l_suppkey /* INT32 */) as profit group by profit.s_nationkey", "Table": "supplier", @@ -1263,9 +1267,7 @@ "Name": "mysqltest", "Sharded": true }, - "NoOfCalls": 1, - "AvgNumberOfRows": 0, - "MedianNumberOfRows": 0, + "ShardsQueried": 1, "FieldQuery": "select count(*), nation from (select n_name as nation from nation where 1 != 1) as profit where 1 != 1 group by nation", "Query": "select count(*), nation from (select n_name as nation from nation where n_nationkey = :s_nationkey /* INT32 */) as profit group by nation", "Table": "nation", @@ -1357,9 +1359,10 @@ "Name": "mysqltest", "Sharded": true }, - "NoOfCalls": 2, + "NoOfCalls": 1, "AvgNumberOfRows": 0, "MedianNumberOfRows": 0, + "ShardsQueried": 2, "FieldQuery": "select sum(l_extendedprice * (1 - l_discount)) as revenue, o_custkey from orders, lineitem where 1 != 1 group by o_custkey", "Query": "select sum(l_extendedprice * (1 - l_discount)) as revenue, o_custkey from orders, lineitem where o_orderdate \u003e= '1993-08-01' and o_orderdate \u003c date_add('1993-08-01', interval '3' month) and l_returnflag = 'R' and l_orderkey = o_orderkey group by o_custkey", "Table": "lineitem, orders" @@ -1393,9 +1396,7 @@ "Name": "mysqltest", "Sharded": true }, - "NoOfCalls": 1, - "AvgNumberOfRows": 0, - "MedianNumberOfRows": 0, + "ShardsQueried": 1, "FieldQuery": "select count(*), c_custkey, c_name, c_acctbal, c_phone, c_address, c_comment, c_nationkey from customer where 1 != 1 group by c_custkey, c_name, c_acctbal, c_phone, c_address, c_comment, c_nationkey", "Query": "select count(*), c_custkey, c_name, c_acctbal, c_phone, c_address, c_comment, c_nationkey from customer where c_custkey = :o_custkey /* INT32 */ group by c_custkey, c_name, c_acctbal, c_phone, c_address, c_comment, c_nationkey", "Table": "customer", @@ -1411,9 +1412,7 @@ "Name": "mysqltest", "Sharded": true }, - "NoOfCalls": 1, - "AvgNumberOfRows": 0, - "MedianNumberOfRows": 0, + "ShardsQueried": 1, "FieldQuery": "select count(*), n_name from nation where 1 != 1 group by n_name", "Query": "select count(*), n_name from nation where n_nationkey = :c_nationkey /* INT32 */ group by n_name", "Table": "nation", @@ -1522,9 +1521,10 @@ "Name": "mysqltest", "Sharded": true }, - "NoOfCalls": 2, + "NoOfCalls": 1, "AvgNumberOfRows": 2, "MedianNumberOfRows": 2, + "ShardsQueried": 2, "FieldQuery": "select sum(ps_supplycost * ps_availqty), 0.0001000000, ps_suppkey from partsupp where 1 != 1 group by ps_suppkey", "Query": "select sum(ps_supplycost * ps_availqty), 0.0001000000, ps_suppkey from partsupp group by ps_suppkey", "Table": "partsupp" @@ -1536,9 +1536,10 @@ "Name": "mysqltest", "Sharded": true }, - "NoOfCalls": 4, + "NoOfCalls": 2, "AvgNumberOfRows": 1, "MedianNumberOfRows": 1, + "ShardsQueried": 2, "FieldQuery": "select count(*), s_nationkey from supplier where 1 != 1 group by s_nationkey", "Query": "select count(*), s_nationkey from supplier where s_suppkey = :ps_suppkey1 /* INT32 */ group by s_nationkey", "Table": "supplier", @@ -1558,9 +1559,10 @@ "Name": "mysqltest", "Sharded": true }, - "NoOfCalls": 4, + "NoOfCalls": 2, "AvgNumberOfRows": 0, "MedianNumberOfRows": 0, + "ShardsQueried": 2, "FieldQuery": "select count(*) from nation where 1 != 1 group by .0", "Query": "select count(*) from nation where n_name = 'MOZAMBIQUE' and n_nationkey = :s_nationkey1 /* INT32 */ group by .0", "Table": "nation", @@ -1654,9 +1656,10 @@ "Name": "mysqltest", "Sharded": true }, - "NoOfCalls": 2, + "NoOfCalls": 1, "AvgNumberOfRows": 3, "MedianNumberOfRows": 3, + "ShardsQueried": 2, "FieldQuery": "select sum(ps_supplycost * ps_availqty) as value, ps_partkey, ps_suppkey from partsupp where 1 != 1 group by ps_partkey, ps_suppkey", "OrderBy": "1 ASC", "Query": "select sum(ps_supplycost * ps_availqty) as value, ps_partkey, ps_suppkey from partsupp group by ps_partkey, ps_suppkey order by ps_partkey asc", @@ -1669,9 +1672,10 @@ "Name": "mysqltest", "Sharded": true }, - "NoOfCalls": 6, + "NoOfCalls": 3, "AvgNumberOfRows": 1, "MedianNumberOfRows": 1, + "ShardsQueried": 3, "FieldQuery": "select count(*), s_nationkey from supplier where 1 != 1 group by s_nationkey", "Query": "select count(*), s_nationkey from supplier where s_suppkey = :ps_suppkey /* INT32 */ group by s_nationkey", "Table": "supplier", @@ -1691,9 +1695,10 @@ "Name": "mysqltest", "Sharded": true }, - "NoOfCalls": 6, + "NoOfCalls": 3, "AvgNumberOfRows": 0, "MedianNumberOfRows": 0, + "ShardsQueried": 3, "FieldQuery": "select count(*) from nation where 1 != 1 group by .0", "Query": "select count(*) from nation where n_name = 'MOZAMBIQUE' and n_nationkey = :s_nationkey /* INT32 */ group by .0", "Table": "nation", @@ -1734,9 +1739,10 @@ "Name": "mysqltest", "Sharded": true }, - "NoOfCalls": 2, + "NoOfCalls": 1, "AvgNumberOfRows": 0, "MedianNumberOfRows": 0, + "ShardsQueried": 2, "FieldQuery": "select l_shipmode, sum(case when o_orderpriority = '1-URGENT' or o_orderpriority = '2-HIGH' then 1 else 0 end) as high_line_count, sum(case when o_orderpriority != '1-URGENT' and o_orderpriority != '2-HIGH' then 1 else 0 end) as low_line_count from orders, lineitem where 1 != 1 group by l_shipmode", "OrderBy": "0 ASC COLLATE utf8mb4_0900_ai_ci", "Query": "select l_shipmode, sum(case when o_orderpriority = '1-URGENT' or o_orderpriority = '2-HIGH' then 1 else 0 end) as high_line_count, sum(case when o_orderpriority != '1-URGENT' and o_orderpriority != '2-HIGH' then 1 else 0 end) as low_line_count from orders, lineitem where l_shipmode in ('RAIL', 'FOB') and l_commitdate \u003c l_receiptdate and l_shipdate \u003c l_commitdate and l_receiptdate \u003e= '1997-01-01' and l_receiptdate \u003c date_add('1997-01-01', interval '1' year) and o_orderkey = l_orderkey group by l_shipmode order by lineitem.l_shipmode asc", @@ -1821,9 +1827,10 @@ "Name": "mysqltest", "Sharded": true }, - "NoOfCalls": 2, + "NoOfCalls": 1, "AvgNumberOfRows": 4, "MedianNumberOfRows": 4, + "ShardsQueried": 2, "FieldQuery": "select count(*), c_custkey from customer where 1 != 1 group by c_custkey", "OrderBy": "1 ASC", "Query": "select count(*), c_custkey from customer group by c_custkey order by c_custkey asc", @@ -1836,9 +1843,10 @@ "Name": "mysqltest", "Sharded": true }, - "NoOfCalls": 8, + "NoOfCalls": 4, "AvgNumberOfRows": 1, "MedianNumberOfRows": 1, + "ShardsQueried": 8, "FieldQuery": "select count(o_orderkey) as c_count from orders where 1 != 1 group by .0", "Query": "select count(o_orderkey) as c_count from orders where o_comment not like '%pending%deposits%' and o_custkey = :c_custkey /* INT32 */ group by .0", "Table": "orders" @@ -1910,9 +1918,10 @@ "Name": "mysqltest", "Sharded": true }, - "NoOfCalls": 2, + "NoOfCalls": 1, "AvgNumberOfRows": 0, "MedianNumberOfRows": 0, + "ShardsQueried": 2, "FieldQuery": "select l_extendedprice, l_discount, l_extendedprice * (1 - l_discount), l_partkey from lineitem where 1 != 1", "Query": "select l_extendedprice, l_discount, l_extendedprice * (1 - l_discount), l_partkey from lineitem where l_shipdate \u003e= '1996-12-01' and l_shipdate \u003c date_add('1996-12-01', interval '1' month)", "Table": "lineitem" @@ -1924,9 +1933,7 @@ "Name": "mysqltest", "Sharded": true }, - "NoOfCalls": 1, - "AvgNumberOfRows": 0, - "MedianNumberOfRows": 0, + "ShardsQueried": 1, "FieldQuery": "select case when p_type like 'PROMO%' then :l_extendedprice /* DECIMAL(15,2) */ * (1 - :l_discount /* DECIMAL(15,2) */) else 0 end from part where 1 != 1", "Query": "select case when p_type like 'PROMO%' then :l_extendedprice /* DECIMAL(15,2) */ * (1 - :l_discount /* DECIMAL(15,2) */) else 0 end from part where p_partkey = :l_partkey /* INT32 */", "Table": "part", @@ -1983,9 +1990,10 @@ "Name": "mysqltest", "Sharded": true }, - "NoOfCalls": 2, + "NoOfCalls": 1, "AvgNumberOfRows": 0, "MedianNumberOfRows": 0, + "ShardsQueried": 2, "FieldQuery": "select s_suppkey from supplier where 1 != 1", "Query": "select s_suppkey from supplier where s_comment like '%Customer%Complaints%'", "Table": "supplier" @@ -1998,9 +2006,10 @@ "Name": "mysqltest", "Sharded": true }, - "NoOfCalls": 2, + "NoOfCalls": 1, "AvgNumberOfRows": 0, "MedianNumberOfRows": 0, + "ShardsQueried": 2, "FieldQuery": "select p_brand, p_type, p_size, ps_suppkey from partsupp, part where 1 != 1 group by p_brand, p_type, p_size, ps_suppkey", "OrderBy": "0 ASC COLLATE utf8mb4_0900_ai_ci, 1 ASC COLLATE utf8mb4_0900_ai_ci, 2 ASC", "Query": "select p_brand, p_type, p_size, ps_suppkey from partsupp, part where p_brand != 'Brand#34' and p_type not like 'LARGE BRUSHED%' and p_size in (48, 19, 12, 4, 41, 7, 21, 39) and p_partkey = ps_partkey and (not :__sq_has_values or ps_suppkey not in ::__sq1) group by p_brand, p_type, p_size, ps_suppkey order by p_brand asc, p_type asc, p_size asc", @@ -2101,9 +2110,10 @@ "Name": "mysqltest", "Sharded": true }, - "NoOfCalls": 2, + "NoOfCalls": 1, "AvgNumberOfRows": 9, "MedianNumberOfRows": 9, + "ShardsQueried": 2, "FieldQuery": "select l_orderkey, sum(l_quantity) from lineitem where 1 != 1 group by l_orderkey", "OrderBy": "0 ASC", "Query": "select l_orderkey, sum(l_quantity) from lineitem group by l_orderkey order by l_orderkey asc", @@ -2121,9 +2131,10 @@ "Name": "mysqltest", "Sharded": true }, - "NoOfCalls": 2, + "NoOfCalls": 1, "AvgNumberOfRows": 0, "MedianNumberOfRows": 0, + "ShardsQueried": 1, "FieldQuery": "select sum(l_quantity), o_orderkey, o_orderdate, o_totalprice, o_custkey from orders, lineitem where 1 != 1 group by o_orderkey, o_orderdate, o_totalprice, o_custkey", "Query": "select sum(l_quantity), o_orderkey, o_orderdate, o_totalprice, o_custkey from orders, lineitem where o_orderkey = l_orderkey and :__sq_has_values and o_orderkey in ::__vals group by o_orderkey, o_orderdate, o_totalprice, o_custkey", "Table": "lineitem, orders", @@ -2141,9 +2152,7 @@ "Name": "mysqltest", "Sharded": true }, - "NoOfCalls": 1, - "AvgNumberOfRows": 0, - "MedianNumberOfRows": 0, + "ShardsQueried": 1, "FieldQuery": "select count(*), c_name, c_custkey from customer where 1 != 1 group by c_name, c_custkey", "Query": "select count(*), c_name, c_custkey from customer where c_custkey = :o_custkey /* INT32 */ group by c_name, c_custkey", "Table": "customer", @@ -2205,9 +2214,10 @@ "Name": "mysqltest", "Sharded": true }, - "NoOfCalls": 2, + "NoOfCalls": 1, "AvgNumberOfRows": 11, "MedianNumberOfRows": 11, + "ShardsQueried": 2, "FieldQuery": "select sum(l_extendedprice * (1 - l_discount)) as revenue, l_partkey, l_quantity, l_shipmode, l_shipinstruct from lineitem where 1 != 1 group by l_partkey, l_quantity, l_shipmode, l_shipinstruct", "Query": "select sum(l_extendedprice * (1 - l_discount)) as revenue, l_partkey, l_quantity, l_shipmode, l_shipinstruct from lineitem group by l_partkey, l_quantity, l_shipmode, l_shipinstruct", "Table": "lineitem" @@ -2219,9 +2229,10 @@ "Name": "mysqltest", "Sharded": true }, - "NoOfCalls": 22, + "NoOfCalls": 11, "AvgNumberOfRows": 0, "MedianNumberOfRows": 0, + "ShardsQueried": 22, "FieldQuery": "select count(*) from part where 1 != 1 group by .0", "Query": "select count(*) from part where p_partkey = :l_partkey /* INT32 */ and p_brand = 'Brand#52' and p_container in ('SM CASE', 'SM BOX', 'SM PACK', 'SM PKG') and :l_quantity /* DECIMAL(15,2) */ \u003e= 4 and :l_quantity /* DECIMAL(15,2) */ \u003c= 4 + 10 and p_size between 1 and 5 and :l_shipmode /* CHAR(10) */ in ('AIR', 'AIR REG') and :l_shipinstruct /* CHAR(25) */ = 'DELIVER IN PERSON' or p_partkey = :l_partkey /* INT32 */ and p_brand = 'Brand#11' and p_container in ('MED BAG', 'MED BOX', 'MED PKG', 'MED PACK') and :l_quantity /* DECIMAL(15,2) */ \u003e= 18 and :l_quantity /* DECIMAL(15,2) */ \u003c= 18 + 10 and p_size between 1 and 10 and :l_shipmode /* CHAR(10) */ in ('AIR', 'AIR REG') and :l_shipinstruct /* CHAR(25) */ = 'DELIVER IN PERSON' or p_partkey = :l_partkey /* INT32 */ and p_brand = 'Brand#51' and p_container in ('LG CASE', 'LG BOX', 'LG PACK', 'LG PKG') and :l_quantity /* DECIMAL(15,2) */ \u003e= 29 and :l_quantity /* DECIMAL(15,2) */ \u003c= 29 + 10 and p_size between 1 and 15 and :l_shipmode /* CHAR(10) */ in ('AIR', 'AIR REG') and :l_shipinstruct /* CHAR(25) */ = 'DELIVER IN PERSON' group by .0", "Table": "part" @@ -2297,9 +2308,10 @@ "Name": "mysqltest", "Sharded": true }, - "NoOfCalls": 2, + "NoOfCalls": 1, "AvgNumberOfRows": 0, "MedianNumberOfRows": 0, + "ShardsQueried": 2, "FieldQuery": "select count(*), l1.l_suppkey from lineitem as l1, orders where 1 != 1 group by l1.l_suppkey", "Query": "select count(*), l1.l_suppkey from lineitem as l1, orders where l1.l_receiptdate \u003e l1.l_commitdate and o_orderstatus = 'F' and o_orderkey = l1.l_orderkey and exists (select 1 from lineitem as l2 where l2.l_orderkey = l1.l_orderkey and l2.l_suppkey != l1.l_suppkey) and not exists (select 1 from lineitem as l3 where l3.l_orderkey = l1.l_orderkey and l3.l_suppkey != l1.l_suppkey and l3.l_receiptdate \u003e l3.l_commitdate) group by l1.l_suppkey", "Table": "lineitem, orders" @@ -2327,9 +2339,7 @@ "Name": "mysqltest", "Sharded": true }, - "NoOfCalls": 1, - "AvgNumberOfRows": 0, - "MedianNumberOfRows": 0, + "ShardsQueried": 1, "FieldQuery": "select count(*), s_name, s_nationkey from supplier where 1 != 1 group by s_name, s_nationkey", "Query": "select count(*), s_name, s_nationkey from supplier where s_suppkey = :l1_l_suppkey /* INT32 */ group by s_name, s_nationkey", "Table": "supplier", @@ -2345,9 +2355,7 @@ "Name": "mysqltest", "Sharded": true }, - "NoOfCalls": 1, - "AvgNumberOfRows": 0, - "MedianNumberOfRows": 0, + "ShardsQueried": 1, "FieldQuery": "select count(*) from nation where 1 != 1 group by .0", "Query": "select count(*) from nation where n_name = 'EGYPT' and n_nationkey = :s_nationkey /* INT32 */ group by .0", "Table": "nation", From 5511f6f21b4f34ac661857b9a65344bc1a4276cb Mon Sep 17 00:00:00 2001 From: Andres Taylor Date: Thu, 19 Sep 2024 15:07:57 +0200 Subject: [PATCH 4/5] list queries in same order as the first trace file Signed-off-by: Andres Taylor --- src/cmd/vtbenchstat/vtbenchstat.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/cmd/vtbenchstat/vtbenchstat.go b/src/cmd/vtbenchstat/vtbenchstat.go index 41913ef..5879d5b 100644 --- a/src/cmd/vtbenchstat/vtbenchstat.go +++ b/src/cmd/vtbenchstat/vtbenchstat.go @@ -236,9 +236,10 @@ func compareTraces(file1, file2 TraceFile) { var s1RouteCalls, s1DataSent, s1MemoryRows, s1ShardsQueried int var s2RouteCalls, s2DataSent, s2MemoryRows, s2ShardsQueried int - for query, s1 := range summary1 { - s2, ok := summary2[query] - if !ok { + for _, q := range file1.Queries { + s1, ok1 := summary1[q.Query] + s2, ok2 := summary2[q.Query] + if !ok1 || !ok2 { continue } totalQueries++ From fc153becc0980efad5d6859961d4287ac3522af8 Mon Sep 17 00:00:00 2001 From: Andres Taylor Date: Thu, 19 Sep 2024 15:53:48 +0200 Subject: [PATCH 5/5] make vtbenchstat testable and write unit_tests Signed-off-by: Andres Taylor --- src/cmd/vtbenchstat/main.go | 5 +- src/cmd/vtbenchstat/vtbenchstat.go | 67 +++++---- src/cmd/vtbenchstat/vtbenchstat_test.go | 180 ++++++++++++++++++++++++ 3 files changed, 222 insertions(+), 30 deletions(-) create mode 100644 src/cmd/vtbenchstat/vtbenchstat_test.go diff --git a/src/cmd/vtbenchstat/main.go b/src/cmd/vtbenchstat/main.go index 390a6cb..ea89af5 100644 --- a/src/cmd/vtbenchstat/main.go +++ b/src/cmd/vtbenchstat/main.go @@ -37,9 +37,8 @@ func main() { } if len(traces) == 1 { - printSummary(traces[0]) + printSummary(os.Stdout, terminalWidth(), highlightQuery, traces[0]) } else { - compareTraces(traces[0], traces[1]) + compareTraces(os.Stdout, terminalWidth(), highlightQuery, traces[0], traces[1]) } } - diff --git a/src/cmd/vtbenchstat/vtbenchstat.go b/src/cmd/vtbenchstat/vtbenchstat.go index 5879d5b..b65b578 100644 --- a/src/cmd/vtbenchstat/vtbenchstat.go +++ b/src/cmd/vtbenchstat/vtbenchstat.go @@ -22,6 +22,7 @@ import ( "github.com/alecthomas/chroma/quick" "github.com/olekukonko/tablewriter" "golang.org/x/term" + "io" "math" "os" "sort" @@ -180,16 +181,15 @@ func limitQueryLength(query string, termWidth int) string { return processedQuery } -func printSummary(file TraceFile) { +func printSummary(out io.Writer, termWidth int, highLighter Highlighter, file TraceFile) { summary := summarizeTraces(file) - termWidth, _, err := term.GetSize(int(os.Stdout.Fd())) - if err != nil { - termWidth = 80 // default to 80 if we can't get the terminal width - } - for _, query := range file.Queries { + for i, query := range file.Queries { + if i > 0 { + fmt.Fprintln(out) + } querySummary := summary[query.Query] - printQuery(query, termWidth, false) - table := tablewriter.NewWriter(os.Stdout) + printQuery(out, termWidth, highLighter, query, false) + table := tablewriter.NewWriter(out) table.SetAutoFormatHeaders(false) table.SetHeader([]string{ "Route Calls", @@ -204,13 +204,23 @@ func printSummary(file TraceFile) { strconv.Itoa(querySummary.ShardsQueried), }) table.Render() - fmt.Println() } } -func printQuery(q TracedQuery, terminalWidth int, significant bool) { - fmt.Printf("%s", queryPrefix) - err := quick.Highlight(os.Stdout, limitQueryLength(q.Query, terminalWidth), "sql", "terminal", "monokai") +type Highlighter func(out io.Writer, query string) error + +func highlightQuery(out io.Writer, query string) error { + return quick.Highlight(out, query, "sql", "terminal", "monokai") +} + +func noHighlight(out io.Writer, query string) error { + _, err := fmt.Fprint(out, query) + return err +} + +func printQuery(out io.Writer, terminalWidth int, highLighter Highlighter, q TracedQuery, significant bool) { + fmt.Fprintf(out, "%s", queryPrefix) + err := highLighter(out, limitQueryLength(q.Query, terminalWidth)) if err != nil { return } @@ -218,19 +228,22 @@ func printQuery(q TracedQuery, terminalWidth int, significant bool) { if significant { improved = " (significant)" } - fmt.Printf("\nLine # %s%s\n", q.LineNumber, improved) + fmt.Fprintf(out, "\nLine # %s%s\n", q.LineNumber, improved) } const significantChangeThreshold = 10 -func compareTraces(file1, file2 TraceFile) { - summary1 := summarizeTraces(file1) - summary2 := summarizeTraces(file2) - +func terminalWidth() int { termWidth, _, err := term.GetSize(int(os.Stdout.Fd())) if err != nil { - termWidth = 80 // default to 80 if we can't get the terminal width + return 80 // default to 80 if we can't get the terminal width } + return termWidth +} + +func compareTraces(out io.Writer, termWidth int, highLighter Highlighter, file1, file2 TraceFile) { + summary1 := summarizeTraces(file1) + summary2 := summarizeTraces(file2) var significantChanges, totalQueries int var s1RouteCalls, s1DataSent, s1MemoryRows, s1ShardsQueried int @@ -244,7 +257,7 @@ func compareTraces(file1, file2 TraceFile) { } totalQueries++ - table := tablewriter.NewWriter(os.Stdout) + table := tablewriter.NewWriter(out) table.SetHeader([]string{"Metric", file1.Name, file2.Name, "Diff", "% Change"}) table.SetAutoFormatHeaders(false) @@ -268,9 +281,9 @@ func compareTraces(file1, file2 TraceFile) { s2MemoryRows += s2.RowsInMemory s2ShardsQueried += s2.ShardsQueried - printQuery(s1.Q, termWidth, significant) + printQuery(out, termWidth, highLighter, s1.Q, significant) table.Render() - fmt.Println() + fmt.Fprintln(out) } totalRouteCallsChange := float64(s2RouteCalls-s1RouteCalls) / float64(s1RouteCalls) * 100 @@ -279,12 +292,12 @@ func compareTraces(file1, file2 TraceFile) { totalShardsQueriedChange := float64(s2ShardsQueried-s1ShardsQueried) / float64(s1ShardsQueried) * 100 // Print summary - fmt.Println("Summary:") - fmt.Printf("- %d out of %d queries showed significant change\n", significantChanges, totalQueries) - fmt.Printf("- Average change in Route Calls: %.2f%%\n", totalRouteCallsChange) - fmt.Printf("- Average change in Data Sent: %.2f%%\n", totalDataSentChange) - fmt.Printf("- Average change in Rows In Memory: %.2f%%\n", totalMemoryRowsChange) - fmt.Printf("- Average change in Shards Queried: %.2f%%\n", totalShardsQueriedChange) + fmt.Fprintln(out, "Summary:") + fmt.Fprintf(out, "- %d out of %d queries showed significant change\n", significantChanges, totalQueries) + fmt.Fprintf(out, "- Average change in Route Calls: %.2f%%\n", totalRouteCallsChange) + fmt.Fprintf(out, "- Average change in Data Sent: %.2f%%\n", totalDataSentChange) + fmt.Fprintf(out, "- Average change in Rows In Memory: %.2f%%\n", totalMemoryRowsChange) + fmt.Fprintf(out, "- Average change in Shards Queried: %.2f%%\n", totalShardsQueriedChange) } // compareMetric compares two metrics and appends the result to the table, returning true if the change is significant diff --git a/src/cmd/vtbenchstat/vtbenchstat_test.go b/src/cmd/vtbenchstat/vtbenchstat_test.go new file mode 100644 index 0000000..5d69134 --- /dev/null +++ b/src/cmd/vtbenchstat/vtbenchstat_test.go @@ -0,0 +1,180 @@ +/* +Copyright 2024 The Vitess Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package main + +import ( + "github.com/stretchr/testify/assert" + "strings" + "testing" +) + +var tf1 = TraceFile{ + Name: "test", + Queries: []TracedQuery{{ + Query: "select * from music", + LineNumber: "1", + Trace: Trace{ + OperatorType: "Route", + Variant: "Scatter", + NoOfCalls: 1, + AvgNumberOfRows: 16, + MedianNumberOfRows: 16, + ShardsQueried: 8, + }, + }, { + Query: "select tbl.foo, tbl2.bar from tbl join tbl2 on tbl.id = tbl2.id order by tbl.baz", + LineNumber: "2", + Trace: Trace{ + OperatorType: "Sort", + Variant: "Memory", + NoOfCalls: 1, + AvgNumberOfRows: 16, + MedianNumberOfRows: 16, + Inputs: []Trace{{ + OperatorType: "Join", + Variant: "Apply", + NoOfCalls: 1, + AvgNumberOfRows: 16, + MedianNumberOfRows: 16, + Inputs: []Trace{{ + OperatorType: "Route", + Variant: "Scatter", + NoOfCalls: 1, + AvgNumberOfRows: 10, + MedianNumberOfRows: 10, + ShardsQueried: 8, + }, { + OperatorType: "Route", + Variant: "EqualUnique", + NoOfCalls: 10, + AvgNumberOfRows: 1, + MedianNumberOfRows: 1, + ShardsQueried: 10, + }}, + }}, + }, + }}, +} +var tf2 = TraceFile{ + Name: "test", + Queries: []TracedQuery{{ + Query: "select * from music", + LineNumber: "1", + Trace: Trace{ + OperatorType: "Route", + Variant: "Scatter", + NoOfCalls: 1, + AvgNumberOfRows: 16, + MedianNumberOfRows: 16, + ShardsQueried: 7, + }, + }, { + Query: "select tbl.foo, tbl2.bar from tbl join tbl2 on tbl.id = tbl2.id order by tbl.baz", + LineNumber: "2", + Trace: Trace{ + OperatorType: "Route", + Variant: "Scatter", + NoOfCalls: 1, + AvgNumberOfRows: 16, + MedianNumberOfRows: 16, + ShardsQueried: 8, + }, + }}, +} + +func TestSummary(t *testing.T) { + t.Run("tf1", func(t *testing.T) { + sb := &strings.Builder{} + printSummary(sb, 80, noHighlight, tf1) + assert.Equal(t, `Query: select * from music +Line # 1 ++-------------+-----------+----------------+----------------+ +| Route Calls | Rows Sent | Rows In Memory | Shards Queried | ++-------------+-----------+----------------+----------------+ +| 1 | 16 | 0 | 8 | ++-------------+-----------+----------------+----------------+ + +Query: select tbl.foo, tbl2.bar from tbl join tbl2 on tbl.id = tbl2.id order ... +Line # 2 ++-------------+-----------+----------------+----------------+ +| Route Calls | Rows Sent | Rows In Memory | Shards Queried | ++-------------+-----------+----------------+----------------+ +| 11 | 20 | 16 | 18 | ++-------------+-----------+----------------+----------------+ +`, sb.String()) + }) + + t.Run("tf2", func(t *testing.T) { + sb := &strings.Builder{} + printSummary(sb, 80, noHighlight, tf2) + assert.Equal(t, `Query: select * from music +Line # 1 ++-------------+-----------+----------------+----------------+ +| Route Calls | Rows Sent | Rows In Memory | Shards Queried | ++-------------+-----------+----------------+----------------+ +| 1 | 16 | 0 | 7 | ++-------------+-----------+----------------+----------------+ + +Query: select tbl.foo, tbl2.bar from tbl join tbl2 on tbl.id = tbl2.id order ... +Line # 2 ++-------------+-----------+----------------+----------------+ +| Route Calls | Rows Sent | Rows In Memory | Shards Queried | ++-------------+-----------+----------------+----------------+ +| 1 | 16 | 0 | 8 | ++-------------+-----------+----------------+----------------+ +`, sb.String()) + }) +} + +func TestCompareFiles(t *testing.T) { + sb := &strings.Builder{} + compareTraces(sb, 80, noHighlight, tf1, tf2) + s := sb.String() + want := `Query: select * from music +Line # 1 (significant) ++----------------+------+------+------+----------+ +| Metric | test | test | Diff | % Change | ++----------------+------+------+------+----------+ +| Route Calls | 1 | 1 | 0 | 0.00% | +| Rows Sent | 16 | 16 | 0 | 0.00% | +| Rows In Memory | 0 | 0 | 0 | NaN% | +| Shards Queried | 8 | 7 | -1 | -12.50% | ++----------------+------+------+------+----------+ + +Query: select tbl.foo, tbl2.bar from tbl join tbl2 on tbl.id = tbl2.id order ... +Line # 2 (significant) ++----------------+------+------+------+----------+ +| Metric | test | test | Diff | % Change | ++----------------+------+------+------+----------+ +| Route Calls | 11 | 1 | -10 | -90.91% | +| Rows Sent | 20 | 16 | -4 | -20.00% | +| Rows In Memory | 16 | 0 | -16 | -100.00% | +| Shards Queried | 18 | 8 | -10 | -55.56% | ++----------------+------+------+------+----------+ + +Summary: +- 2 out of 2 queries showed significant change +- Average change in Route Calls: -83.33% +- Average change in Data Sent: -11.11% +- Average change in Rows In Memory: -100.00% +- Average change in Shards Queried: -42.31% +` + if s != want { + panic("oh noes") + } + assert.Equal(t, want, s) +}