summaryrefslogtreecommitdiff
path: root/postgres/postgres.go
diff options
context:
space:
mode:
Diffstat (limited to 'postgres/postgres.go')
-rw-r--r--postgres/postgres.go35
1 files changed, 33 insertions, 2 deletions
diff --git a/postgres/postgres.go b/postgres/postgres.go
index 3a5221e..5333f8d 100644
--- a/postgres/postgres.go
+++ b/postgres/postgres.go
@@ -3,6 +3,8 @@ package postgres
import (
"encoding/json"
"fmt"
+ "math"
+ "time"
"github.com/jmoiron/sqlx"
_ "github.com/lib/pq"
@@ -139,10 +141,39 @@ func (db *DB) Analyze(query string) ([]*Explain, error) {
}
var exp []*Explain
- if err := json.Unmarshal([]byte(plan.Plan), &exp); err != nil {
- // if err := json.Unmarshal([]byte(testPlan), &a); err != nil {
+ // if err := json.Unmarshal([]byte(plan.Plan), &exp); err != nil {
+ if err := json.Unmarshal([]byte(testPlan), &exp); err != nil {
return nil, fmt.Errorf("could not unmarshal plan: %v", err)
}
return exp, nil
}
+
+func (p *Plan) EffectiveTotalTime() time.Duration {
+ var childTime time.Duration
+ for _, p := range p.Plans {
+ childTime = childTime + f2d(p.ActualTotalTime)
+ }
+ return f2d(p.ActualTotalTime) - childTime
+}
+
+func (p *Plan) EstimateWrongness() (string, int) {
+ plan, actual := float64(p.PlanRows), float64(p.ActualRows)
+ bigger, smaller := math.Max(plan, actual), math.Min(plan, actual)
+ ratio := int(bigger / smaller)
+ if plan > actual {
+ return "over", ratio
+ }
+ return "under", ratio
+}
+
+func (p *Plan) IsBadEstimate() bool {
+ _, ratio := p.EstimateWrongness()
+ return ratio >= 100
+}
+
+func f2d(f float32) time.Duration {
+ // f is in milliseconds, multiply by 1k to get microseconds
+ // (thousandths of milliseconds)
+ return time.Duration(int(f)*1000) * time.Microsecond
+}