├── .go-version
├── .travis.yml
├── go.mod
├── Dockerfile
├── .gitignore
├── .golangci.yaml
├── .goreleaser.yml
├── go.sum
├── main.go
├── pkg
├── plan
│ ├── plan.go
│ └── plan_test.go
└── html
│ ├── html.go
│ ├── html_test.go
│ └── template.go
├── README.md
├── docs
├── plan.json
├── flamegraph.html
├── cte.json
└── cte_flamegraph.html
└── LICENSE
/.go-version:
--------------------------------------------------------------------------------
1 | 1.13.1
2 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: go
2 |
3 | go:
4 | - 1.13.x
5 |
--------------------------------------------------------------------------------
/go.mod:
--------------------------------------------------------------------------------
1 | module pg_flame
2 |
3 | go 1.13
4 |
5 | require github.com/stretchr/testify v1.4.0
6 |
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM golang:1.13
2 |
3 | WORKDIR /go/src
4 |
5 | RUN cd /go/src \
6 | && git clone https://github.com/mgartner/pg_flame.git \
7 | && cd pg_flame \
8 | && go build
9 |
10 | ENTRYPOINT [ "pg_flame/pg_flame" ]
11 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Binaries for programs and plugins
2 | *.exe
3 | *.exe~
4 | *.dll
5 | *.so
6 | *.dylib
7 |
8 | # Test binary, build with `go test -c`
9 | *.test
10 |
11 | # Output of the go coverage tool, specifically when used with LiteIDE
12 | *.out
13 |
14 | # The produced binary
15 | pg_flame
16 |
17 | # Common name of flamegraph output
18 | flamegraph.html
19 |
20 | # Distribution directory
21 | dist
22 |
--------------------------------------------------------------------------------
/.golangci.yaml:
--------------------------------------------------------------------------------
1 | output:
2 | format: tab
3 | linters:
4 | disable-all: true
5 | enable:
6 | - deadcode
7 | - depguard
8 | - dupl
9 | - goconst
10 | - gocritic
11 | - gocyclo
12 | - gofmt
13 | - goimports
14 | - golint
15 | - gosec
16 | - govet
17 | - ineffassign
18 | - maligned
19 | - misspell
20 | - prealloc
21 | - scopelint
22 | - structcheck
23 | - typecheck
24 | - unconvert
25 | - varcheck
26 | issues:
27 | exclude-use-default: false
28 | max-per-linter: 0
29 | max-same-issues: 0
30 |
--------------------------------------------------------------------------------
/.goreleaser.yml:
--------------------------------------------------------------------------------
1 | # This is an example goreleaser.yaml file with some sane defaults.
2 | # Make sure to check the documentation at http://goreleaser.com
3 | builds:
4 | - env:
5 | - CGO_ENABLED=0
6 | archives:
7 | - replacements:
8 | darwin: Darwin
9 | linux: Linux
10 | 386: i386
11 | amd64: x86_64
12 | checksum:
13 | name_template: 'checksums.txt'
14 | snapshot:
15 | name_template: "{{ .Tag }}-next"
16 | changelog:
17 | sort: asc
18 | brews:
19 | -
20 | name: pg_flame
21 | goarm: 6
22 | github:
23 | owner: mgartner
24 | name: homebrew-tap
25 | folder: Formula
26 | homepage: "https://github.com/mgartner/pg_flame"
27 | description: "A flamegraph generator for Postgres EXPLAIN ANALYZE output."
28 |
--------------------------------------------------------------------------------
/go.sum:
--------------------------------------------------------------------------------
1 | github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
2 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
3 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
4 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
5 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
6 | github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
7 | github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
8 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
9 | gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
10 | gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
11 |
--------------------------------------------------------------------------------
/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "flag"
5 | "fmt"
6 | "os"
7 |
8 | "pg_flame/pkg/html"
9 | "pg_flame/pkg/plan"
10 | )
11 |
12 | var (
13 | // goreleaser automatically overrides this based on the tag
14 | version = "dev"
15 | hFlag = flag.Bool("h", false, "print help info")
16 | helpFlag = flag.Bool("help", false, "print help info")
17 | )
18 |
19 | func main() {
20 | flag.Parse()
21 |
22 | if *hFlag || *helpFlag {
23 | printHelp()
24 | }
25 |
26 | p, err := plan.New(os.Stdin)
27 | if err != nil {
28 | handleErr(err)
29 | }
30 |
31 | err = html.Generate(os.Stdout, p)
32 | if err != nil {
33 | handleErr(err)
34 | }
35 | }
36 |
37 | func handleErr(err error) {
38 | fmt.Fprintf(os.Stderr, "Error: %v", err)
39 | os.Exit(1)
40 | }
41 |
42 | func printHelp() {
43 | help := `pg_flame %s
44 |
45 | Turn Postgres query plans into flamegraphs.
46 |
47 | Usage:
48 |
49 | pg_flame [options]
50 |
51 | Without Options:
52 |
53 | Reads a JSON query plan from standard input and writes the
54 | flamegraph html to standard output.
55 |
56 | Options:
57 |
58 | -h, --help print help information
59 | `
60 |
61 | fmt.Printf(help, version)
62 | os.Exit(0)
63 | }
64 |
--------------------------------------------------------------------------------
/pkg/plan/plan.go:
--------------------------------------------------------------------------------
1 | package plan
2 |
3 | import (
4 | "encoding/json"
5 | "errors"
6 | "io"
7 | )
8 |
9 | type Plan struct {
10 | PlanningTime float64 `json:"Planning Time"`
11 | ExecutionTree Node `json:"Plan"`
12 | }
13 |
14 | type Node struct {
15 | Method string `json:"Node Type"`
16 | Table string `json:"Relation Name"`
17 | Alias string `json:"Alias"`
18 | Index string `json:"Index Name"`
19 | ParentRelationship string `json:"Parent Relationship"`
20 | PlanCost float64 `json:"Total Cost"`
21 | PlanRows int `json:"Plan Rows"`
22 | PlanWidth int `json:"Plan Width"`
23 | ActualTotalTime float64 `json:"Actual Total Time"`
24 | ActualRows int `json:"Actual Rows"`
25 | ActualLoops int `json:"Actual Loops"`
26 | Filter string `json:"Filter"`
27 | JoinFilter string `json:"Join Filter"`
28 | HashCond string `json:"Hash Cond"`
29 | IndexCond string `json:"Index Cond"`
30 | RecheckCond string `json:"Recheck Cond"`
31 | BuffersHit int `json:"Shared Hit Blocks"`
32 | BuffersRead int `json:"Shared Read Blocks"`
33 | MemoryUsage int `json:"Peak Memory Usage"`
34 | HashBuckets int `json:"Hash Buckets"`
35 | HashBatches int `json:"Hash Batches"`
36 | SortKey []string `json:"Sort Key"`
37 | SortMethod string `json:"Sort Method"`
38 | SortSpaceUsed int `json:"Sort Space Used"`
39 | SortSpaceType string `json:"Sort Space Type"`
40 | Children []Node `json:"Plans"`
41 | }
42 |
43 | var ErrEmptyPlanJSON = errors.New("empty plan JSON")
44 | var ErrInvalidPlanJSON = errors.New("invalid plan JSON")
45 |
46 | func New(r io.Reader) (Plan, error) {
47 | var plans []Plan
48 |
49 | err := json.NewDecoder(r).Decode(&plans)
50 | if err != nil {
51 | var e *json.UnmarshalTypeError
52 | if errors.As(err, &e) {
53 | err = ErrInvalidPlanJSON
54 | }
55 | return Plan{}, err
56 | }
57 |
58 | if len(plans) < 1 {
59 | return Plan{}, ErrEmptyPlanJSON
60 | }
61 |
62 | return plans[0], nil
63 | }
64 |
--------------------------------------------------------------------------------
/pkg/html/html.go:
--------------------------------------------------------------------------------
1 | package html
2 |
3 | import (
4 | "bytes"
5 | "fmt"
6 | "io"
7 |
8 | "pg_flame/pkg/plan"
9 | )
10 |
11 | type Flame struct {
12 | Name string `json:"name"`
13 | Value float64 `json:"value"`
14 | Time float64 `json:"time"`
15 | Detail string `json:"detail"`
16 | Color string `json:"color"`
17 | InitPlan bool `json:"init_plan"`
18 | Children []Flame `json:"children"`
19 | }
20 |
21 | const detailSpan = "%s "
22 |
23 | const colorPlan = "#00C05A"
24 | const colorInit = "#C0C0C0"
25 |
26 | func Generate(w io.Writer, p plan.Plan) error {
27 | f, err := buildFlame(p)
28 | if err != nil {
29 | return err
30 | }
31 |
32 | err = templateHTML.Execute(w, f)
33 | if err != nil {
34 | return err
35 | }
36 |
37 | return nil
38 | }
39 |
40 | func buildFlame(p plan.Plan) (Flame, error) {
41 | planningFlame := Flame{
42 | Name: "Query Planning",
43 | Value: p.PlanningTime,
44 | Time: p.PlanningTime,
45 | Detail: fmt.Sprintf(detailSpan, "Time to generate the query plan"),
46 | Color: colorPlan,
47 | }
48 |
49 | executionFlame, err := convertPlanNode(p.ExecutionTree, "")
50 | if err != nil {
51 | return Flame{}, err
52 | }
53 |
54 | return Flame{
55 | Name: "Total",
56 | Value: planningFlame.Value + executionFlame.Value,
57 | Time: planningFlame.Time + executionFlame.Time,
58 | Detail: fmt.Sprintf(detailSpan, "Includes planning and execution time"),
59 | Children: []Flame{planningFlame, executionFlame},
60 | }, nil
61 | }
62 |
63 | func convertPlanNode(n plan.Node, color string) (Flame, error) {
64 | initPlan := n.ParentRelationship == "InitPlan"
65 | value := n.ActualTotalTime
66 |
67 | if initPlan {
68 | color = colorInit
69 | }
70 |
71 | var childFlames []Flame
72 | for _, childNode := range n.Children {
73 |
74 | // Pass the color forward for grey InitPlan trees
75 | f, err := convertPlanNode(childNode, color)
76 | if err != nil {
77 | return Flame{}, err
78 | }
79 |
80 | // Add to the total value if the child is an InitPlan node
81 | if f.InitPlan {
82 | value += f.Value
83 | }
84 |
85 | childFlames = append(childFlames, f)
86 | }
87 |
88 | d, err := detail(n)
89 | if err != nil {
90 | return Flame{}, err
91 | }
92 |
93 | return Flame{
94 | Name: name(n),
95 | Value: value,
96 | Time: n.ActualTotalTime,
97 | Detail: d,
98 | Color: color,
99 | InitPlan: initPlan,
100 | Children: childFlames,
101 | }, nil
102 | }
103 |
104 | func name(n plan.Node) string {
105 | switch {
106 | case n.Table != "" && n.Index != "":
107 | return fmt.Sprintf("%s using %s on %s", n.Method, n.Index, n.Table)
108 | case n.Table != "":
109 | return fmt.Sprintf("%s on %s", n.Method, n.Table)
110 | default:
111 | return n.Method
112 | }
113 | }
114 |
115 | func detail(n plan.Node) (string, error) {
116 | var b bytes.Buffer
117 |
118 | err := templateTable.Execute(&b, n)
119 | if err != nil {
120 | return "", err
121 | }
122 |
123 | return b.String(), nil
124 | }
125 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # pg_flame [](https://github.com/mgartner/pg_flame/releases) [](https://travis-ci.com/mgartner/pg_flame)
2 |
3 | A flamegraph generator for Postgres `EXPLAIN ANALYZE` output.
4 |
5 |
6 |
7 |
8 |
9 | ## Demo
10 |
11 | Try the demo [here](https://mgartner.github.io/pg_flame/flamegraph.html).
12 |
13 | ## Installation
14 |
15 | ### Homebrew
16 |
17 | You can install via Homebrew with the follow command:
18 |
19 | ```
20 | $ brew install mgartner/tap/pg_flame
21 | ```
22 |
23 | ### Download pre-compiled binary
24 |
25 | Download one of the compiled binaries [in the releases
26 | tab](https://github.com/mgartner/pg_flame/releases). Once downloaded, move
27 | `pg_flame` into your `$PATH`.
28 |
29 | ### Docker
30 |
31 | Alternatively, if you'd like to use Docker to build the program, you can.
32 |
33 | ```
34 | $ docker pull mgartner/pg_flame
35 | ```
36 |
37 | ### Build from source
38 |
39 | If you'd like to build a binary from the source code, run the following
40 | commands. Note that compiling requires Go version 1.13+.
41 |
42 | ```
43 | $ git clone https://github.com/mgartner/pg_flame.git
44 | $ cd pg_flame
45 | $ go build
46 | ```
47 |
48 | A `pg_flame` binary will be created that you can place in your `$PATH`.
49 |
50 | ## Usage
51 |
52 | The `pg_flame` program reads a JSON query plan from standard input and writes
53 | the flamegraph HTML to standard ouput. Therefore you can pipe and direct input
54 | and output however you desire.
55 |
56 | ### Example: One-step
57 |
58 | ```bash
59 | $ psql dbname -qAtc 'EXPLAIN (ANALYZE, BUFFERS, FORMAT JSON) SELECT id FROM users' \
60 | | pg_flame \
61 | > flamegraph.html \
62 | && open flamegraph.html
63 | ```
64 |
65 | ### Example: Multi-step with SQL file
66 |
67 | Create a SQL file with the `EXPLAIN ANALYZE` query.
68 |
69 | ```sql
70 | -- query.sql
71 | EXPLAIN (ANALYZE, BUFFERS, FORMAT JSON)
72 | SELECT id
73 | FROM users
74 | ```
75 |
76 | Then run the query and save the JSON to a file.
77 |
78 | ```bash
79 | $ psql dbname -qAtf query.sql > plan.json
80 | ```
81 |
82 | Finally, generate the flamegraph HTML.
83 |
84 | ```
85 | $ cat plan.json | pg_flame > flamegraph.html
86 | ```
87 |
88 | ### Example: Docker
89 |
90 | If you've followed the Docker installation steps above, you can pipe query plan
91 | JSON to a container and save the output HTML.
92 |
93 | ```
94 | $ psql dbname -qAtc 'EXPLAIN (ANALYZE, BUFFERS, FORMAT JSON) SELECT id FROM users' \
95 | | docker run -i pg_flame \
96 | > flamegraph.html
97 | ```
98 |
99 | ## Background
100 |
101 | [Flamegraphs](http://www.brendangregg.com/flamegraphs.html) were invented by
102 | Brendan Gregg to visualize CPU consumption per code-path of profiled software.
103 | They are useful visualization tools in many types of performance
104 | investigations. Flamegraphs have been used to visualize Oracle database
105 | [query
106 | plans](https://blog.tanelpoder.com/posts/visualizing-sql-plan-execution-time-with-flamegraphs/)
107 | and [query
108 | executions](https://externaltable.blogspot.com/2014/05/flame-graphs-for-oracle.html)
109 | , proving useful for debugging slow database queries.
110 |
111 | Pg_flame is in extension of that work for Postgres query plans. It generates a
112 | visual hierarchy of query plans. This visualization identifies the relative
113 | time of each part of a query plan.
114 |
115 | This tool relies on the
116 | [`spiermar/d3-flame-graph`](https://github.com/spiermar/d3-flame-graph) plugin to
117 | generate the flamegraph.
118 |
--------------------------------------------------------------------------------
/pkg/html/html_test.go:
--------------------------------------------------------------------------------
1 | package html
2 |
3 | import (
4 | "bytes"
5 | "testing"
6 |
7 | "github.com/stretchr/testify/assert"
8 | "pg_flame/pkg/plan"
9 | )
10 |
11 | func TestNew(t *testing.T) {
12 |
13 | t.Run("writes an HTML flamegraph based on a Flame", func(t *testing.T) {
14 | p := plan.Plan{
15 | ExecutionTree: plan.Node{
16 | Table: "bears",
17 | ActualTotalTime: 0.022,
18 | },
19 | }
20 |
21 | b := new(bytes.Buffer)
22 |
23 | err := Generate(b, p)
24 |
25 | assert.NoError(t, err)
26 |
27 | assert.Contains(t, b.String(), p.ExecutionTree.Table)
28 | })
29 |
30 | }
31 |
32 | func Test_buildFlame(t *testing.T) {
33 |
34 | t.Run("creates a new Flame from a Plan", func(t *testing.T) {
35 | p := plan.Plan{
36 | PlanningTime: 0.01,
37 | ExecutionTree: plan.Node{
38 | Method: "Limit",
39 | ActualTotalTime: 0.123,
40 | Children: []plan.Node{
41 | {
42 | Method: "Seq Scan",
43 | Table: "bears",
44 | ActualTotalTime: 0.022,
45 | },
46 | },
47 | },
48 | }
49 |
50 | f, err := buildFlame(p)
51 |
52 | assert.NoError(t, err)
53 |
54 | assert.Equal(t, "Total", f.Name)
55 | assert.Equal(t, 0.133, f.Value)
56 | assert.Equal(t, 0.133, f.Time)
57 | assert.Equal(t, "Includes planning and execution time ", f.Detail)
58 |
59 | assert.Equal(t, "Query Planning", f.Children[0].Name)
60 | assert.Equal(t, colorPlan, f.Children[0].Color)
61 | assert.Equal(t, 0.01, f.Children[0].Value)
62 | assert.Equal(t, 0.01, f.Children[0].Time)
63 | assert.Equal(t, "Time to generate the query plan ", f.Children[0].Detail)
64 |
65 | assert.Equal(t, "Limit", f.Children[1].Name)
66 | assert.Equal(t, 0.123, f.Children[1].Value)
67 | assert.Equal(t, 0.123, f.Children[1].Time)
68 |
69 | assert.Equal(t, "Seq Scan on bears", f.Children[1].Children[0].Name)
70 | assert.Equal(t, 0.022, f.Children[1].Children[0].Value)
71 | assert.Equal(t, 0.022, f.Children[1].Children[0].Time)
72 | })
73 |
74 | t.Run("handles InitPlan nodes", func(t *testing.T) {
75 | p := plan.Plan{
76 | ExecutionTree: plan.Node{
77 | Method: "Seq Scan",
78 | ActualTotalTime: 0.12,
79 | Children: []plan.Node{
80 | {
81 | Method: "Seq Scan",
82 | Table: "bears",
83 | ParentRelationship: "InitPlan",
84 | ActualTotalTime: 0.2,
85 | Children: []plan.Node{
86 | {
87 | Method: "Seq Scan",
88 | ActualTotalTime: 0.12,
89 | },
90 | },
91 | },
92 | },
93 | },
94 | }
95 |
96 | f, err := buildFlame(p)
97 |
98 | assert.NoError(t, err)
99 |
100 | assert.Equal(t, "Total", f.Name)
101 | assert.Equal(t, 0.32, f.Value)
102 | assert.Equal(t, 0.12, f.Time)
103 |
104 | assert.Equal(t, "Seq Scan", f.Children[1].Name)
105 | assert.Equal(t, 0.32, f.Children[1].Value)
106 | assert.Equal(t, 0.12, f.Children[1].Time)
107 | assert.Equal(t, "", f.Children[1].Color)
108 | assert.False(t, f.Children[1].InitPlan)
109 |
110 | assert.Equal(t, "Seq Scan on bears", f.Children[1].Children[0].Name)
111 | assert.Equal(t, 0.2, f.Children[1].Children[0].Value)
112 | assert.Equal(t, 0.2, f.Children[1].Children[0].Time)
113 | assert.Equal(t, colorInit, f.Children[1].Children[0].Color)
114 | assert.True(t, f.Children[1].Children[0].InitPlan)
115 |
116 | assert.Equal(t, colorInit, f.Children[1].Children[0].Children[0].Color)
117 | })
118 |
119 | }
120 |
121 | func Test_name(t *testing.T) {
122 |
123 | t.Run("returns the method and table if table exists", func(t *testing.T) {
124 | n := plan.Node{
125 | Method: "Seq Scan",
126 | Table: "bears",
127 | }
128 |
129 | assert.Equal(t, "Seq Scan on bears", name(n))
130 | })
131 |
132 | t.Run("returns the method, index, and table if table exists", func(t *testing.T) {
133 | n := plan.Node{
134 | Method: "Index Scan",
135 | Table: "bears",
136 | Index: "bears_pkey",
137 | }
138 |
139 | assert.Equal(t, "Index Scan using bears_pkey on bears", name(n))
140 | })
141 |
142 | t.Run("returns the method if there is no table", func(t *testing.T) {
143 | n := plan.Node{Method: "Seq Scan"}
144 |
145 | assert.Equal(t, "Seq Scan", name(n))
146 | })
147 |
148 | }
149 |
150 | func Test_detail(t *testing.T) {
151 |
152 | t.Run("returns a table of details", func(t *testing.T) {
153 | n := plan.Node{
154 | Filter: "(id = 123)",
155 | MemoryUsage: 12,
156 | }
157 |
158 | d, err := detail(n)
159 |
160 | assert.NoError(t, err)
161 |
162 | assert.Contains(t, d, n.Filter)
163 | assert.Contains(t, d, "12 kB")
164 | })
165 |
166 | }
167 |
--------------------------------------------------------------------------------
/pkg/plan/plan_test.go:
--------------------------------------------------------------------------------
1 | package plan
2 |
3 | import (
4 | "strings"
5 | "testing"
6 |
7 | "github.com/stretchr/testify/assert"
8 | )
9 |
10 | func TestNew(t *testing.T) {
11 |
12 | t.Run("decodes EXPLAIN ANALYZE plan JSON", func(t *testing.T) {
13 | input := strings.NewReader(planJSON)
14 |
15 | p, err := New(input)
16 |
17 | assert.NoError(t, err)
18 |
19 | assert.Equal(t, "Nested Loop", p.ExecutionTree.Method)
20 | assert.Equal(t, "", p.ExecutionTree.Table)
21 | assert.Equal(t, 0.049, p.ExecutionTree.ActualTotalTime)
22 |
23 | child := p.ExecutionTree.Children[0]
24 |
25 | assert.Equal(t, "Hash Join", child.Method)
26 | assert.Equal(t, "users", child.Table)
27 | assert.Equal(t, "users_pkey", child.Index)
28 | assert.Equal(t, "u", child.Alias)
29 | assert.Equal(t, "Outer", child.ParentRelationship)
30 |
31 | assert.Equal(t, 35.06, child.PlanCost)
32 | assert.Equal(t, 1, child.PlanRows)
33 | assert.Equal(t, 543, child.PlanWidth)
34 |
35 | assert.Equal(t, 0.049, child.ActualTotalTime)
36 | assert.Equal(t, 5, child.ActualRows)
37 | assert.Equal(t, 1, child.ActualLoops)
38 |
39 | assert.Equal(t, "((title)::text ~ '.*sql.*'::text)", child.Filter)
40 | assert.Equal(t, "(id = 123)", child.JoinFilter)
41 | assert.Equal(t, "((p.user_id = c.user_id) AND (p.id = c.post_id))", child.HashCond)
42 | assert.Equal(t, "(id = p.user_id)", child.IndexCond)
43 | assert.Equal(t, "(p.user_id = 123)", child.RecheckCond)
44 |
45 | assert.Equal(t, 5, child.BuffersHit)
46 | assert.Equal(t, 1, child.BuffersRead)
47 |
48 | assert.Equal(t, 1024, child.HashBuckets)
49 | assert.Equal(t, 1, child.HashBatches)
50 | assert.Equal(t, 8, child.MemoryUsage)
51 |
52 | assert.Equal(t, []string{"u.id", "u.email DESC"}, child.SortKey)
53 | assert.Equal(t, "quicksort", child.SortMethod)
54 | assert.Equal(t, 33, child.SortSpaceUsed)
55 | assert.Equal(t, "Memory", child.SortSpaceType)
56 | })
57 |
58 | t.Run("returns an error with empty plan JSON", func(t *testing.T) {
59 | input := strings.NewReader("[]")
60 |
61 | _, err := New(input)
62 |
63 | assert.Error(t, err)
64 | assert.Equal(t, ErrEmptyPlanJSON, err)
65 | })
66 |
67 | t.Run("returns an error with invalid plan JSON", func(t *testing.T) {
68 | input := strings.NewReader("{}")
69 |
70 | _, err := New(input)
71 |
72 | assert.Error(t, err)
73 | assert.Equal(t, ErrInvalidPlanJSON, err)
74 | })
75 |
76 | t.Run("returns an error with invalid JSON syntax", func(t *testing.T) {
77 | input := strings.NewReader("[}")
78 |
79 | _, err := New(input)
80 |
81 | assert.Error(t, err)
82 | })
83 |
84 | }
85 |
86 | const planJSON = `
87 | [
88 | {
89 | "Plan": {
90 | "Node Type": "Nested Loop",
91 | "Parallel Aware": false,
92 | "Join Type": "Inner",
93 | "Startup Cost": 265.38,
94 | "Total Cost": 288.42,
95 | "Plan Rows": 1,
96 | "Plan Width": 539,
97 | "Actual Startup Time": 0.049,
98 | "Actual Total Time": 0.049,
99 | "Actual Rows": 0,
100 | "Actual Loops": 1,
101 | "Inner Unique": true,
102 | "Shared Hit Blocks": 5,
103 | "Shared Read Blocks": 1,
104 | "Shared Dirtied Blocks": 0,
105 | "Shared Written Blocks": 0,
106 | "Local Hit Blocks": 0,
107 | "Local Read Blocks": 0,
108 | "Local Dirtied Blocks": 0,
109 | "Local Written Blocks": 0,
110 | "Temp Read Blocks": 0,
111 | "Temp Written Blocks": 0,
112 | "Plans": [
113 | {
114 | "Node Type": "Hash Join",
115 | "Relation Name": "users",
116 | "Alias": "u",
117 | "Index Name": "users_pkey",
118 | "Parent Relationship": "Outer",
119 | "Parallel Aware": false,
120 | "Join Type": "Inner",
121 | "Startup Cost": 13.50,
122 | "Total Cost": 35.06,
123 | "Plan Rows": 1,
124 | "Plan Width": 543,
125 | "Actual Startup Time": 0.049,
126 | "Actual Total Time": 0.049,
127 | "Actual Rows": 5,
128 | "Actual Loops": 1,
129 | "Inner Unique": false,
130 | "Filter": "((title)::text ~ '.*sql.*'::text)",
131 | "Hash Cond": "((p.user_id = c.user_id) AND (p.id = c.post_id))",
132 | "Index Cond": "(id = p.user_id)",
133 | "Join Filter": "(id = 123)",
134 | "Recheck Cond": "(p.user_id = 123)",
135 | "Hash Buckets": 1024,
136 | "Hash Batches": 1,
137 | "Peak Memory Usage": 8,
138 | "Shared Hit Blocks": 5,
139 | "Shared Read Blocks": 1,
140 | "Shared Dirtied Blocks": 0,
141 | "Shared Written Blocks": 0,
142 | "Sort Key": ["u.id", "u.email DESC"],
143 | "Sort Method": "quicksort",
144 | "Sort Space Used": 33,
145 | "Sort Space Type": "Memory",
146 | "Local Hit Blocks": 0,
147 | "Local Read Blocks": 0,
148 | "Local Dirtied Blocks": 0,
149 | "Local Written Blocks": 0,
150 | "Temp Read Blocks": 0,
151 | "Temp Written Blocks": 0,
152 | "Plans": [
153 | ]
154 | }
155 | ]
156 | },
157 | "Planning Time": 2.523,
158 | "Triggers": [
159 | ],
160 | "Execution Time": 0.221
161 | }
162 | ]
163 | `
164 |
--------------------------------------------------------------------------------
/docs/plan.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "Plan": {
4 | "Node Type": "Sort",
5 | "Parallel Aware": false,
6 | "Startup Cost": 2864.87,
7 | "Total Cost": 2869.01,
8 | "Plan Rows": 1657,
9 | "Plan Width": 33,
10 | "Actual Startup Time": 48.641,
11 | "Actual Total Time": 48.649,
12 | "Actual Rows": 106,
13 | "Actual Loops": 1,
14 | "Sort Key": ["u.id", "u.email DESC"],
15 | "Sort Method": "quicksort",
16 | "Sort Space Used": 33,
17 | "Sort Space Type": "Memory",
18 | "Shared Hit Blocks": 821,
19 | "Shared Read Blocks": 0,
20 | "Shared Dirtied Blocks": 0,
21 | "Shared Written Blocks": 0,
22 | "Local Hit Blocks": 0,
23 | "Local Read Blocks": 0,
24 | "Local Dirtied Blocks": 0,
25 | "Local Written Blocks": 0,
26 | "Temp Read Blocks": 0,
27 | "Temp Written Blocks": 0,
28 | "Plans": [
29 | {
30 | "Node Type": "Aggregate",
31 | "Strategy": "Hashed",
32 | "Partial Mode": "Simple",
33 | "Parent Relationship": "Outer",
34 | "Parallel Aware": false,
35 | "Startup Cost": 2714.13,
36 | "Total Cost": 2776.27,
37 | "Plan Rows": 1657,
38 | "Plan Width": 33,
39 | "Actual Startup Time": 48.048,
40 | "Actual Total Time": 48.557,
41 | "Actual Rows": 106,
42 | "Actual Loops": 1,
43 | "Group Key": ["u.id"],
44 | "Filter": "(count(*) > 1)",
45 | "Rows Removed by Filter": 4758,
46 | "Shared Hit Blocks": 815,
47 | "Shared Read Blocks": 0,
48 | "Shared Dirtied Blocks": 0,
49 | "Shared Written Blocks": 0,
50 | "Local Hit Blocks": 0,
51 | "Local Read Blocks": 0,
52 | "Local Dirtied Blocks": 0,
53 | "Local Written Blocks": 0,
54 | "Temp Read Blocks": 0,
55 | "Temp Written Blocks": 0,
56 | "Plans": [
57 | {
58 | "Node Type": "Hash Join",
59 | "Parent Relationship": "Outer",
60 | "Parallel Aware": false,
61 | "Join Type": "Inner",
62 | "Startup Cost": 271.14,
63 | "Total Cost": 2676.85,
64 | "Plan Rows": 4971,
65 | "Plan Width": 25,
66 | "Actual Startup Time": 18.000,
67 | "Actual Total Time": 46.020,
68 | "Actual Rows": 4971,
69 | "Actual Loops": 1,
70 | "Inner Unique": false,
71 | "Hash Cond": "(u.id = posts.user_id)",
72 | "Shared Hit Blocks": 815,
73 | "Shared Read Blocks": 0,
74 | "Shared Dirtied Blocks": 0,
75 | "Shared Written Blocks": 0,
76 | "Local Hit Blocks": 0,
77 | "Local Read Blocks": 0,
78 | "Local Dirtied Blocks": 0,
79 | "Local Written Blocks": 0,
80 | "Temp Read Blocks": 0,
81 | "Temp Written Blocks": 0,
82 | "Plans": [
83 | {
84 | "Node Type": "Seq Scan",
85 | "Parent Relationship": "Outer",
86 | "Parallel Aware": false,
87 | "Relation Name": "users",
88 | "Alias": "u",
89 | "Startup Cost": 0.00,
90 | "Total Cost": 1731.00,
91 | "Plan Rows": 100000,
92 | "Plan Width": 25,
93 | "Actual Startup Time": 0.015,
94 | "Actual Total Time": 12.836,
95 | "Actual Rows": 100000,
96 | "Actual Loops": 1,
97 | "Shared Hit Blocks": 731,
98 | "Shared Read Blocks": 0,
99 | "Shared Dirtied Blocks": 0,
100 | "Shared Written Blocks": 0,
101 | "Local Hit Blocks": 0,
102 | "Local Read Blocks": 0,
103 | "Local Dirtied Blocks": 0,
104 | "Local Written Blocks": 0,
105 | "Temp Read Blocks": 0,
106 | "Temp Written Blocks": 0
107 | },
108 | {
109 | "Node Type": "Hash",
110 | "Parent Relationship": "Inner",
111 | "Parallel Aware": false,
112 | "Startup Cost": 209.00,
113 | "Total Cost": 209.00,
114 | "Plan Rows": 4971,
115 | "Plan Width": 4,
116 | "Actual Startup Time": 17.893,
117 | "Actual Total Time": 17.894,
118 | "Actual Rows": 4971,
119 | "Actual Loops": 1,
120 | "Hash Buckets": 8192,
121 | "Original Hash Buckets": 8192,
122 | "Hash Batches": 1,
123 | "Original Hash Batches": 1,
124 | "Peak Memory Usage": 239,
125 | "Shared Hit Blocks": 84,
126 | "Shared Read Blocks": 0,
127 | "Shared Dirtied Blocks": 0,
128 | "Shared Written Blocks": 0,
129 | "Local Hit Blocks": 0,
130 | "Local Read Blocks": 0,
131 | "Local Dirtied Blocks": 0,
132 | "Local Written Blocks": 0,
133 | "Temp Read Blocks": 0,
134 | "Temp Written Blocks": 0,
135 | "Plans": [
136 | {
137 | "Node Type": "Seq Scan",
138 | "Parent Relationship": "Outer",
139 | "Parallel Aware": false,
140 | "Relation Name": "posts",
141 | "Alias": "posts",
142 | "Startup Cost": 0.00,
143 | "Total Cost": 209.00,
144 | "Plan Rows": 4971,
145 | "Plan Width": 4,
146 | "Actual Startup Time": 0.032,
147 | "Actual Total Time": 16.073,
148 | "Actual Rows": 4971,
149 | "Actual Loops": 1,
150 | "Filter": "((title)::text ~ '.*sql.*'::text)",
151 | "Rows Removed by Filter": 5029,
152 | "Shared Hit Blocks": 84,
153 | "Shared Read Blocks": 0,
154 | "Shared Dirtied Blocks": 0,
155 | "Shared Written Blocks": 0,
156 | "Local Hit Blocks": 0,
157 | "Local Read Blocks": 0,
158 | "Local Dirtied Blocks": 0,
159 | "Local Written Blocks": 0,
160 | "Temp Read Blocks": 0,
161 | "Temp Written Blocks": 0
162 | }
163 | ]
164 | }
165 | ]
166 | }
167 | ]
168 | }
169 | ]
170 | },
171 | "Planning Time": 1.641,
172 | "Triggers": [
173 | ],
174 | "Execution Time": 48.942
175 | }
176 | ]
177 |
--------------------------------------------------------------------------------
/pkg/html/template.go:
--------------------------------------------------------------------------------
1 | package html
2 |
3 | import (
4 | "html/template"
5 | )
6 |
7 | var templateHTML *template.Template = template.Must(template.New("html").Parse(`
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
62 |
63 | pg_flame
64 |
65 |
66 |
70 |
71 |
72 |
73 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
158 |
159 |
160 | `))
161 |
162 | var templateTable *template.Template = template.Must(template.New("table").Parse(`
163 |
164 |
165 | {{if .Method}}
166 |
167 | Method
168 | {{.Method}}
169 |
170 | {{end}}
171 | {{if .Table}}
172 |
173 | Table
174 | {{.Table}}
175 |
176 | {{end}}
177 | {{if .Index}}
178 |
179 | Index
180 | {{.Index}}
181 |
182 | {{end}}
183 | {{if .Alias}}
184 |
185 | Alias
186 | {{.Alias}}
187 |
188 | {{end}}
189 | {{if .ParentRelationship}}
190 |
191 | Parent Relationship
192 | {{.ParentRelationship}}
193 |
194 | {{end}}
195 | {{if .PlanCost}}
196 |
197 | Plan Cost
198 | {{.PlanCost}}
199 |
200 | {{end}}
201 | {{if .PlanRows}}
202 |
203 | Plan Rows
204 | {{.PlanRows}}
205 |
206 | {{end}}
207 | {{if .PlanWidth}}
208 |
209 | Plan Width
210 | {{.PlanWidth}}
211 |
212 | {{end}}
213 | {{if .ActualTotalTime}}
214 |
215 | Actual Total Time
216 | {{.ActualTotalTime}} ms
217 |
218 | {{end}}
219 | {{if .ActualRows}}
220 |
221 | Actual Rows
222 | {{.ActualRows}}
223 |
224 | {{end}}
225 | {{if .ActualLoops}}
226 |
227 | Actual Loops
228 | {{.ActualLoops}}
229 |
230 | {{end}}
231 | {{if .Filter}}
232 |
233 | Filter
234 | {{.Filter}}
235 |
236 | {{end}}
237 | {{if .JoinFilter}}
238 |
239 | Join Filter
240 | {{.JoinFilter}}
241 |
242 | {{end}}
243 | {{if .HashCond}}
244 |
245 | Hash Cond
246 | {{.HashCond}}
247 |
248 | {{end}}
249 | {{if .IndexCond}}
250 |
251 | Index Cond
252 | {{.IndexCond}}
253 |
254 | {{end}}
255 | {{if .RecheckCond}}
256 |
257 | Recheck Cond
258 | {{.RecheckCond}}
259 |
260 | {{end}}
261 | {{if .BuffersHit}}
262 |
263 | Buffers Shared Hit
264 | {{.BuffersHit}}
265 |
266 | {{end}}
267 | {{if .BuffersRead}}
268 |
269 | Buffers Shared Read
270 | {{.BuffersRead}}
271 |
272 | {{end}}
273 | {{if .HashBuckets}}
274 |
275 | Hash Buckets
276 | {{.HashBuckets}}
277 |
278 | {{end}}
279 | {{if .HashBatches}}
280 |
281 | Hash Batches
282 | {{.HashBatches}}
283 |
284 | {{end}}
285 | {{if .MemoryUsage}}
286 |
287 | Memory Usage
288 | {{.MemoryUsage}} kB
289 |
290 | {{end}}
291 | {{if .SortKey}}
292 |
293 | Sort Key
294 | {{.SortKey}}
295 |
296 | {{end}}
297 | {{if .SortMethod}}
298 |
299 | Sort Method
300 | {{.SortMethod}}
301 |
302 | {{end}}
303 | {{if .SortSpaceUsed}}
304 |
305 | Sort Space Used
306 | {{.SortSpaceUsed}} kB
307 |
308 | {{end}}
309 | {{if .SortSpaceType}}
310 |
311 | Sort Space Type
312 | {{.SortSpaceType}}
313 |
314 | {{end}}
315 |
316 |
317 | `))
318 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "[]"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright [yyyy] [name of copyright owner]
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/docs/flamegraph.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
56 |
57 | pg_flame
58 |
59 |
60 |
61 |
62 |
63 |
64 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
149 |
150 |
151 |
--------------------------------------------------------------------------------
/docs/cte.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "Plan": {
4 | "Node Type": "Aggregate",
5 | "Strategy": "Sorted",
6 | "Partial Mode": "Simple",
7 | "Parallel Aware": false,
8 | "Startup Cost": 15552.51,
9 | "Total Cost": 15554.36,
10 | "Plan Rows": 1,
11 | "Plan Width": 33,
12 | "Actual Startup Time": 755.383,
13 | "Actual Total Time": 755.383,
14 | "Actual Rows": 0,
15 | "Actual Loops": 1,
16 | "Group Key": ["u.id"],
17 | "Filter": "(count(*) > 1)",
18 | "Rows Removed by Filter": 0,
19 | "Shared Hit Blocks": 2957,
20 | "Shared Read Blocks": 0,
21 | "Shared Dirtied Blocks": 0,
22 | "Shared Written Blocks": 0,
23 | "Local Hit Blocks": 0,
24 | "Local Read Blocks": 0,
25 | "Local Dirtied Blocks": 0,
26 | "Local Written Blocks": 0,
27 | "Temp Read Blocks": 0,
28 | "Temp Written Blocks": 0,
29 | "Plans": [
30 | {
31 | "Node Type": "Seq Scan",
32 | "Parent Relationship": "InitPlan",
33 | "Subplan Name": "CTE sql_posts",
34 | "Parallel Aware": false,
35 | "Relation Name": "posts",
36 | "Alias": "posts",
37 | "Startup Cost": 0.00,
38 | "Total Cost": 209.00,
39 | "Plan Rows": 4971,
40 | "Plan Width": 36,
41 | "Actual Startup Time": 0.023,
42 | "Actual Total Time": 0.023,
43 | "Actual Rows": 1,
44 | "Actual Loops": 1,
45 | "Filter": "((title)::text ~ '.*sql.*'::text)",
46 | "Rows Removed by Filter": 1,
47 | "Shared Hit Blocks": 1,
48 | "Shared Read Blocks": 0,
49 | "Shared Dirtied Blocks": 0,
50 | "Shared Written Blocks": 0,
51 | "Local Hit Blocks": 0,
52 | "Local Read Blocks": 0,
53 | "Local Dirtied Blocks": 0,
54 | "Local Written Blocks": 0,
55 | "Temp Read Blocks": 0,
56 | "Temp Written Blocks": 0
57 | },
58 | {
59 | "Node Type": "Seq Scan",
60 | "Parent Relationship": "InitPlan",
61 | "Subplan Name": "CTE postgres_posts",
62 | "Parallel Aware": false,
63 | "Relation Name": "posts",
64 | "Alias": "posts_1",
65 | "Startup Cost": 0.00,
66 | "Total Cost": 209.00,
67 | "Plan Rows": 2481,
68 | "Plan Width": 36,
69 | "Actual Startup Time": 0.032,
70 | "Actual Total Time": 0.032,
71 | "Actual Rows": 1,
72 | "Actual Loops": 1,
73 | "Filter": "((title)::text ~ '.*postgres.*'::text)",
74 | "Rows Removed by Filter": 13,
75 | "Shared Hit Blocks": 1,
76 | "Shared Read Blocks": 0,
77 | "Shared Dirtied Blocks": 0,
78 | "Shared Written Blocks": 0,
79 | "Local Hit Blocks": 0,
80 | "Local Read Blocks": 0,
81 | "Local Dirtied Blocks": 0,
82 | "Local Written Blocks": 0,
83 | "Temp Read Blocks": 0,
84 | "Temp Written Blocks": 0
85 | },
86 | {
87 | "Node Type": "Seq Scan",
88 | "Parent Relationship": "InitPlan",
89 | "Subplan Name": "CTE database_posts",
90 | "Parallel Aware": false,
91 | "Relation Name": "posts",
92 | "Alias": "posts_2",
93 | "Startup Cost": 0.00,
94 | "Total Cost": 209.00,
95 | "Plan Rows": 2548,
96 | "Plan Width": 36,
97 | "Actual Startup Time": 0.010,
98 | "Actual Total Time": 0.010,
99 | "Actual Rows": 1,
100 | "Actual Loops": 1,
101 | "Filter": "((title)::text ~ '.*databases.*'::text)",
102 | "Rows Removed by Filter": 0,
103 | "Shared Hit Blocks": 1,
104 | "Shared Read Blocks": 0,
105 | "Shared Dirtied Blocks": 0,
106 | "Shared Written Blocks": 0,
107 | "Local Hit Blocks": 0,
108 | "Local Read Blocks": 0,
109 | "Local Dirtied Blocks": 0,
110 | "Local Written Blocks": 0,
111 | "Temp Read Blocks": 0,
112 | "Temp Written Blocks": 0
113 | },
114 | {
115 | "Node Type": "Nested Loop",
116 | "Parent Relationship": "InitPlan",
117 | "Subplan Name": "CTE performance_comments",
118 | "Parallel Aware": false,
119 | "Join Type": "Inner",
120 | "Startup Cost": 0.29,
121 | "Total Cost": 2242.31,
122 | "Plan Rows": 1,
123 | "Plan Width": 25,
124 | "Actual Startup Time": 223.165,
125 | "Actual Total Time": 223.165,
126 | "Actual Rows": 0,
127 | "Actual Loops": 1,
128 | "Inner Unique": true,
129 | "Shared Hit Blocks": 984,
130 | "Shared Read Blocks": 0,
131 | "Shared Dirtied Blocks": 0,
132 | "Shared Written Blocks": 0,
133 | "Local Hit Blocks": 0,
134 | "Local Read Blocks": 0,
135 | "Local Dirtied Blocks": 0,
136 | "Local Written Blocks": 0,
137 | "Temp Read Blocks": 0,
138 | "Temp Written Blocks": 0,
139 | "Plans": [
140 | {
141 | "Node Type": "Seq Scan",
142 | "Parent Relationship": "Outer",
143 | "Parallel Aware": false,
144 | "Relation Name": "comments",
145 | "Alias": "c",
146 | "Startup Cost": 0.00,
147 | "Total Cost": 2234.00,
148 | "Plan Rows": 1,
149 | "Plan Width": 4,
150 | "Actual Startup Time": 223.164,
151 | "Actual Total Time": 223.164,
152 | "Actual Rows": 0,
153 | "Actual Loops": 1,
154 | "Filter": "((body)::text ~ '.*performance.*'::text)",
155 | "Rows Removed by Filter": 100000,
156 | "Shared Hit Blocks": 984,
157 | "Shared Read Blocks": 0,
158 | "Shared Dirtied Blocks": 0,
159 | "Shared Written Blocks": 0,
160 | "Local Hit Blocks": 0,
161 | "Local Read Blocks": 0,
162 | "Local Dirtied Blocks": 0,
163 | "Local Written Blocks": 0,
164 | "Temp Read Blocks": 0,
165 | "Temp Written Blocks": 0
166 | },
167 | {
168 | "Node Type": "Index Scan",
169 | "Parent Relationship": "Inner",
170 | "Parallel Aware": false,
171 | "Scan Direction": "Forward",
172 | "Index Name": "users_pkey",
173 | "Relation Name": "users",
174 | "Alias": "u_1",
175 | "Startup Cost": 0.29,
176 | "Total Cost": 8.31,
177 | "Plan Rows": 1,
178 | "Plan Width": 25,
179 | "Actual Startup Time": 0.000,
180 | "Actual Total Time": 0.000,
181 | "Actual Rows": 0,
182 | "Actual Loops": 0,
183 | "Index Cond": "(id = c.user_id)",
184 | "Rows Removed by Index Recheck": 0,
185 | "Shared Hit Blocks": 0,
186 | "Shared Read Blocks": 0,
187 | "Shared Dirtied Blocks": 0,
188 | "Shared Written Blocks": 0,
189 | "Local Hit Blocks": 0,
190 | "Local Read Blocks": 0,
191 | "Local Dirtied Blocks": 0,
192 | "Local Written Blocks": 0,
193 | "Temp Read Blocks": 0,
194 | "Temp Written Blocks": 0
195 | }
196 | ]
197 | },
198 | {
199 | "Node Type": "Hash Join",
200 | "Parent Relationship": "InitPlan",
201 | "Subplan Name": "CTE testing_comments",
202 | "Parallel Aware": false,
203 | "Join Type": "Inner",
204 | "Startup Cost": 2861.59,
205 | "Total Cost": 5594.66,
206 | "Plan Rows": 50207,
207 | "Plan Width": 25,
208 | "Actual Startup Time": 252.949,
209 | "Actual Total Time": 252.949,
210 | "Actual Rows": 1,
211 | "Actual Loops": 1,
212 | "Inner Unique": false,
213 | "Hash Cond": "(u_2.id = c_1.user_id)",
214 | "Shared Hit Blocks": 985,
215 | "Shared Read Blocks": 0,
216 | "Shared Dirtied Blocks": 0,
217 | "Shared Written Blocks": 0,
218 | "Local Hit Blocks": 0,
219 | "Local Read Blocks": 0,
220 | "Local Dirtied Blocks": 0,
221 | "Local Written Blocks": 0,
222 | "Temp Read Blocks": 0,
223 | "Temp Written Blocks": 0,
224 | "Plans": [
225 | {
226 | "Node Type": "Seq Scan",
227 | "Parent Relationship": "Outer",
228 | "Parallel Aware": false,
229 | "Relation Name": "users",
230 | "Alias": "u_2",
231 | "Startup Cost": 0.00,
232 | "Total Cost": 1731.00,
233 | "Plan Rows": 100000,
234 | "Plan Width": 25,
235 | "Actual Startup Time": 0.016,
236 | "Actual Total Time": 0.017,
237 | "Actual Rows": 3,
238 | "Actual Loops": 1,
239 | "Shared Hit Blocks": 1,
240 | "Shared Read Blocks": 0,
241 | "Shared Dirtied Blocks": 0,
242 | "Shared Written Blocks": 0,
243 | "Local Hit Blocks": 0,
244 | "Local Read Blocks": 0,
245 | "Local Dirtied Blocks": 0,
246 | "Local Written Blocks": 0,
247 | "Temp Read Blocks": 0,
248 | "Temp Written Blocks": 0
249 | },
250 | {
251 | "Node Type": "Hash",
252 | "Parent Relationship": "Inner",
253 | "Parallel Aware": false,
254 | "Startup Cost": 2234.00,
255 | "Total Cost": 2234.00,
256 | "Plan Rows": 50207,
257 | "Plan Width": 4,
258 | "Actual Startup Time": 252.611,
259 | "Actual Total Time": 252.611,
260 | "Actual Rows": 49998,
261 | "Actual Loops": 1,
262 | "Hash Buckets": 65536,
263 | "Original Hash Buckets": 65536,
264 | "Hash Batches": 1,
265 | "Original Hash Batches": 1,
266 | "Peak Memory Usage": 2270,
267 | "Shared Hit Blocks": 984,
268 | "Shared Read Blocks": 0,
269 | "Shared Dirtied Blocks": 0,
270 | "Shared Written Blocks": 0,
271 | "Local Hit Blocks": 0,
272 | "Local Read Blocks": 0,
273 | "Local Dirtied Blocks": 0,
274 | "Local Written Blocks": 0,
275 | "Temp Read Blocks": 0,
276 | "Temp Written Blocks": 0,
277 | "Plans": [
278 | {
279 | "Node Type": "Seq Scan",
280 | "Parent Relationship": "Outer",
281 | "Parallel Aware": false,
282 | "Relation Name": "comments",
283 | "Alias": "c_1",
284 | "Startup Cost": 0.00,
285 | "Total Cost": 2234.00,
286 | "Plan Rows": 50207,
287 | "Plan Width": 4,
288 | "Actual Startup Time": 0.035,
289 | "Actual Total Time": 239.699,
290 | "Actual Rows": 49998,
291 | "Actual Loops": 1,
292 | "Filter": "((body)::text ~ '.*testing.*'::text)",
293 | "Rows Removed by Filter": 50002,
294 | "Shared Hit Blocks": 984,
295 | "Shared Read Blocks": 0,
296 | "Shared Dirtied Blocks": 0,
297 | "Shared Written Blocks": 0,
298 | "Local Hit Blocks": 0,
299 | "Local Read Blocks": 0,
300 | "Local Dirtied Blocks": 0,
301 | "Local Written Blocks": 0,
302 | "Temp Read Blocks": 0,
303 | "Temp Written Blocks": 0
304 | }
305 | ]
306 | }
307 | ]
308 | },
309 | {
310 | "Node Type": "Hash Join",
311 | "Parent Relationship": "InitPlan",
312 | "Subplan Name": "CTE modularity_comments",
313 | "Parallel Aware": false,
314 | "Join Type": "Inner",
315 | "Startup Cost": 2545.59,
316 | "Total Cost": 5025.86,
317 | "Plan Rows": 24927,
318 | "Plan Width": 25,
319 | "Actual Startup Time": 279.072,
320 | "Actual Total Time": 279.073,
321 | "Actual Rows": 1,
322 | "Actual Loops": 1,
323 | "Inner Unique": false,
324 | "Hash Cond": "(u_3.id = c_2.user_id)",
325 | "Shared Hit Blocks": 985,
326 | "Shared Read Blocks": 0,
327 | "Shared Dirtied Blocks": 0,
328 | "Shared Written Blocks": 0,
329 | "Local Hit Blocks": 0,
330 | "Local Read Blocks": 0,
331 | "Local Dirtied Blocks": 0,
332 | "Local Written Blocks": 0,
333 | "Temp Read Blocks": 0,
334 | "Temp Written Blocks": 0,
335 | "Plans": [
336 | {
337 | "Node Type": "Seq Scan",
338 | "Parent Relationship": "Outer",
339 | "Parallel Aware": false,
340 | "Relation Name": "users",
341 | "Alias": "u_3",
342 | "Startup Cost": 0.00,
343 | "Total Cost": 1731.00,
344 | "Plan Rows": 100000,
345 | "Plan Width": 25,
346 | "Actual Startup Time": 0.012,
347 | "Actual Total Time": 0.012,
348 | "Actual Rows": 1,
349 | "Actual Loops": 1,
350 | "Shared Hit Blocks": 1,
351 | "Shared Read Blocks": 0,
352 | "Shared Dirtied Blocks": 0,
353 | "Shared Written Blocks": 0,
354 | "Local Hit Blocks": 0,
355 | "Local Read Blocks": 0,
356 | "Local Dirtied Blocks": 0,
357 | "Local Written Blocks": 0,
358 | "Temp Read Blocks": 0,
359 | "Temp Written Blocks": 0
360 | },
361 | {
362 | "Node Type": "Hash",
363 | "Parent Relationship": "Inner",
364 | "Parallel Aware": false,
365 | "Startup Cost": 2234.00,
366 | "Total Cost": 2234.00,
367 | "Plan Rows": 24927,
368 | "Plan Width": 4,
369 | "Actual Startup Time": 278.911,
370 | "Actual Total Time": 278.911,
371 | "Actual Rows": 25058,
372 | "Actual Loops": 1,
373 | "Hash Buckets": 32768,
374 | "Original Hash Buckets": 32768,
375 | "Hash Batches": 1,
376 | "Original Hash Batches": 1,
377 | "Peak Memory Usage": 1137,
378 | "Shared Hit Blocks": 984,
379 | "Shared Read Blocks": 0,
380 | "Shared Dirtied Blocks": 0,
381 | "Shared Written Blocks": 0,
382 | "Local Hit Blocks": 0,
383 | "Local Read Blocks": 0,
384 | "Local Dirtied Blocks": 0,
385 | "Local Written Blocks": 0,
386 | "Temp Read Blocks": 0,
387 | "Temp Written Blocks": 0,
388 | "Plans": [
389 | {
390 | "Node Type": "Seq Scan",
391 | "Parent Relationship": "Outer",
392 | "Parallel Aware": false,
393 | "Relation Name": "comments",
394 | "Alias": "c_2",
395 | "Startup Cost": 0.00,
396 | "Total Cost": 2234.00,
397 | "Plan Rows": 24927,
398 | "Plan Width": 4,
399 | "Actual Startup Time": 0.025,
400 | "Actual Total Time": 271.456,
401 | "Actual Rows": 25058,
402 | "Actual Loops": 1,
403 | "Filter": "((body)::text ~ '.*modularity.*'::text)",
404 | "Rows Removed by Filter": 74942,
405 | "Shared Hit Blocks": 984,
406 | "Shared Read Blocks": 0,
407 | "Shared Dirtied Blocks": 0,
408 | "Shared Written Blocks": 0,
409 | "Local Hit Blocks": 0,
410 | "Local Read Blocks": 0,
411 | "Local Dirtied Blocks": 0,
412 | "Local Written Blocks": 0,
413 | "Temp Read Blocks": 0,
414 | "Temp Written Blocks": 0
415 | }
416 | ]
417 | }
418 | ]
419 | },
420 | {
421 | "Node Type": "Index Scan",
422 | "Parent Relationship": "InitPlan",
423 | "Subplan Name": "CTE early_gmail_users",
424 | "Parallel Aware": false,
425 | "Scan Direction": "Forward",
426 | "Index Name": "users_pkey",
427 | "Relation Name": "users",
428 | "Alias": "users",
429 | "Startup Cost": 0.29,
430 | "Total Cost": 10.23,
431 | "Plan Rows": 25,
432 | "Plan Width": 4,
433 | "Actual Startup Time": 0.000,
434 | "Actual Total Time": 0.000,
435 | "Actual Rows": 0,
436 | "Actual Loops": 0,
437 | "Index Cond": "(id < 100)",
438 | "Rows Removed by Index Recheck": 0,
439 | "Filter": "((email)::text ~ '.*gmail.*'::text)",
440 | "Rows Removed by Filter": 0,
441 | "Shared Hit Blocks": 0,
442 | "Shared Read Blocks": 0,
443 | "Shared Dirtied Blocks": 0,
444 | "Shared Written Blocks": 0,
445 | "Local Hit Blocks": 0,
446 | "Local Read Blocks": 0,
447 | "Local Dirtied Blocks": 0,
448 | "Local Written Blocks": 0,
449 | "Temp Read Blocks": 0,
450 | "Temp Written Blocks": 0
451 | },
452 | {
453 | "Node Type": "Index Scan",
454 | "Parent Relationship": "InitPlan",
455 | "Subplan Name": "CTE early_yahoo_users",
456 | "Parallel Aware": false,
457 | "Scan Direction": "Forward",
458 | "Index Name": "users_pkey",
459 | "Relation Name": "users",
460 | "Alias": "users_1",
461 | "Startup Cost": 0.29,
462 | "Total Cost": 10.23,
463 | "Plan Rows": 16,
464 | "Plan Width": 4,
465 | "Actual Startup Time": 0.000,
466 | "Actual Total Time": 0.000,
467 | "Actual Rows": 0,
468 | "Actual Loops": 0,
469 | "Index Cond": "(id < 100)",
470 | "Rows Removed by Index Recheck": 0,
471 | "Filter": "((email)::text ~ '.*yahoo.*'::text)",
472 | "Rows Removed by Filter": 0,
473 | "Shared Hit Blocks": 0,
474 | "Shared Read Blocks": 0,
475 | "Shared Dirtied Blocks": 0,
476 | "Shared Written Blocks": 0,
477 | "Local Hit Blocks": 0,
478 | "Local Read Blocks": 0,
479 | "Local Dirtied Blocks": 0,
480 | "Local Written Blocks": 0,
481 | "Temp Read Blocks": 0,
482 | "Temp Written Blocks": 0
483 | },
484 | {
485 | "Node Type": "Index Scan",
486 | "Parent Relationship": "InitPlan",
487 | "Subplan Name": "CTE early_hotmail_users",
488 | "Parallel Aware": false,
489 | "Scan Direction": "Forward",
490 | "Index Name": "users_pkey",
491 | "Relation Name": "users",
492 | "Alias": "users_2",
493 | "Startup Cost": 0.29,
494 | "Total Cost": 10.23,
495 | "Plan Rows": 56,
496 | "Plan Width": 4,
497 | "Actual Startup Time": 0.000,
498 | "Actual Total Time": 0.000,
499 | "Actual Rows": 0,
500 | "Actual Loops": 0,
501 | "Index Cond": "(id < 100)",
502 | "Rows Removed by Index Recheck": 0,
503 | "Filter": "((email)::text ~ '.*hotmail.*'::text)",
504 | "Rows Removed by Filter": 0,
505 | "Shared Hit Blocks": 0,
506 | "Shared Read Blocks": 0,
507 | "Shared Dirtied Blocks": 0,
508 | "Shared Written Blocks": 0,
509 | "Local Hit Blocks": 0,
510 | "Local Read Blocks": 0,
511 | "Local Dirtied Blocks": 0,
512 | "Local Written Blocks": 0,
513 | "Temp Read Blocks": 0,
514 | "Temp Written Blocks": 0
515 | },
516 | {
517 | "Node Type": "Nested Loop",
518 | "Parent Relationship": "Outer",
519 | "Parallel Aware": false,
520 | "Join Type": "Inner",
521 | "Startup Cost": 2031.99,
522 | "Total Cost": 2033.82,
523 | "Plan Rows": 1,
524 | "Plan Width": 25,
525 | "Actual Startup Time": 755.380,
526 | "Actual Total Time": 755.380,
527 | "Actual Rows": 0,
528 | "Actual Loops": 1,
529 | "Inner Unique": false,
530 | "Join Filter": "(eyu.id = u.id)",
531 | "Rows Removed by Join Filter": 0,
532 | "Shared Hit Blocks": 2957,
533 | "Shared Read Blocks": 0,
534 | "Shared Dirtied Blocks": 0,
535 | "Shared Written Blocks": 0,
536 | "Local Hit Blocks": 0,
537 | "Local Read Blocks": 0,
538 | "Local Dirtied Blocks": 0,
539 | "Local Written Blocks": 0,
540 | "Temp Read Blocks": 0,
541 | "Temp Written Blocks": 0,
542 | "Plans": [
543 | {
544 | "Node Type": "Merge Join",
545 | "Parent Relationship": "Outer",
546 | "Parallel Aware": false,
547 | "Join Type": "Inner",
548 | "Startup Cost": 2031.47,
549 | "Total Cost": 2031.61,
550 | "Plan Rows": 1,
551 | "Plan Width": 53,
552 | "Actual Startup Time": 755.379,
553 | "Actual Total Time": 755.380,
554 | "Actual Rows": 0,
555 | "Actual Loops": 1,
556 | "Inner Unique": false,
557 | "Merge Cond": "(u.id = egu.id)",
558 | "Shared Hit Blocks": 2957,
559 | "Shared Read Blocks": 0,
560 | "Shared Dirtied Blocks": 0,
561 | "Shared Written Blocks": 0,
562 | "Local Hit Blocks": 0,
563 | "Local Read Blocks": 0,
564 | "Local Dirtied Blocks": 0,
565 | "Local Written Blocks": 0,
566 | "Temp Read Blocks": 0,
567 | "Temp Written Blocks": 0,
568 | "Plans": [
569 | {
570 | "Node Type": "Sort",
571 | "Parent Relationship": "Outer",
572 | "Parallel Aware": false,
573 | "Startup Cost": 2030.39,
574 | "Total Cost": 2030.39,
575 | "Plan Rows": 1,
576 | "Plan Width": 49,
577 | "Actual Startup Time": 755.378,
578 | "Actual Total Time": 755.379,
579 | "Actual Rows": 0,
580 | "Actual Loops": 1,
581 | "Sort Key": ["u.id"],
582 | "Sort Method": "quicksort",
583 | "Sort Space Used": 25,
584 | "Sort Space Type": "Memory",
585 | "Shared Hit Blocks": 2957,
586 | "Shared Read Blocks": 0,
587 | "Shared Dirtied Blocks": 0,
588 | "Shared Written Blocks": 0,
589 | "Local Hit Blocks": 0,
590 | "Local Read Blocks": 0,
591 | "Local Dirtied Blocks": 0,
592 | "Local Written Blocks": 0,
593 | "Temp Read Blocks": 0,
594 | "Temp Written Blocks": 0,
595 | "Plans": [
596 | {
597 | "Node Type": "Hash Join",
598 | "Parent Relationship": "Outer",
599 | "Parallel Aware": false,
600 | "Join Type": "Inner",
601 | "Startup Cost": 837.95,
602 | "Total Cost": 2030.38,
603 | "Plan Rows": 1,
604 | "Plan Width": 49,
605 | "Actual Startup Time": 755.357,
606 | "Actual Total Time": 755.357,
607 | "Actual Rows": 0,
608 | "Actual Loops": 1,
609 | "Inner Unique": false,
610 | "Hash Cond": "(tc.user_id = u.id)",
611 | "Shared Hit Blocks": 2957,
612 | "Shared Read Blocks": 0,
613 | "Shared Dirtied Blocks": 0,
614 | "Shared Written Blocks": 0,
615 | "Local Hit Blocks": 0,
616 | "Local Read Blocks": 0,
617 | "Local Dirtied Blocks": 0,
618 | "Local Written Blocks": 0,
619 | "Temp Read Blocks": 0,
620 | "Temp Written Blocks": 0,
621 | "Plans": [
622 | {
623 | "Node Type": "CTE Scan",
624 | "Parent Relationship": "Outer",
625 | "Parallel Aware": false,
626 | "CTE Name": "testing_comments",
627 | "Alias": "tc",
628 | "Startup Cost": 0.00,
629 | "Total Cost": 1004.14,
630 | "Plan Rows": 50207,
631 | "Plan Width": 4,
632 | "Actual Startup Time": 252.951,
633 | "Actual Total Time": 252.951,
634 | "Actual Rows": 1,
635 | "Actual Loops": 1,
636 | "Shared Hit Blocks": 985,
637 | "Shared Read Blocks": 0,
638 | "Shared Dirtied Blocks": 0,
639 | "Shared Written Blocks": 0,
640 | "Local Hit Blocks": 0,
641 | "Local Read Blocks": 0,
642 | "Local Dirtied Blocks": 0,
643 | "Local Written Blocks": 0,
644 | "Temp Read Blocks": 0,
645 | "Temp Written Blocks": 0
646 | },
647 | {
648 | "Node Type": "Hash",
649 | "Parent Relationship": "Inner",
650 | "Parallel Aware": false,
651 | "Startup Cost": 837.94,
652 | "Total Cost": 837.94,
653 | "Plan Rows": 1,
654 | "Plan Width": 45,
655 | "Actual Startup Time": 502.388,
656 | "Actual Total Time": 502.388,
657 | "Actual Rows": 0,
658 | "Actual Loops": 1,
659 | "Hash Buckets": 1024,
660 | "Original Hash Buckets": 1024,
661 | "Hash Batches": 1,
662 | "Original Hash Batches": 1,
663 | "Peak Memory Usage": 8,
664 | "Shared Hit Blocks": 1972,
665 | "Shared Read Blocks": 0,
666 | "Shared Dirtied Blocks": 0,
667 | "Shared Written Blocks": 0,
668 | "Local Hit Blocks": 0,
669 | "Local Read Blocks": 0,
670 | "Local Dirtied Blocks": 0,
671 | "Local Written Blocks": 0,
672 | "Temp Read Blocks": 0,
673 | "Temp Written Blocks": 0,
674 | "Plans": [
675 | {
676 | "Node Type": "Hash Join",
677 | "Parent Relationship": "Outer",
678 | "Parallel Aware": false,
679 | "Join Type": "Inner",
680 | "Startup Cost": 245.91,
681 | "Total Cost": 837.94,
682 | "Plan Rows": 1,
683 | "Plan Width": 45,
684 | "Actual Startup Time": 502.387,
685 | "Actual Total Time": 502.387,
686 | "Actual Rows": 0,
687 | "Actual Loops": 1,
688 | "Inner Unique": false,
689 | "Hash Cond": "(mc.user_id = u.id)",
690 | "Shared Hit Blocks": 1972,
691 | "Shared Read Blocks": 0,
692 | "Shared Dirtied Blocks": 0,
693 | "Shared Written Blocks": 0,
694 | "Local Hit Blocks": 0,
695 | "Local Read Blocks": 0,
696 | "Local Dirtied Blocks": 0,
697 | "Local Written Blocks": 0,
698 | "Temp Read Blocks": 0,
699 | "Temp Written Blocks": 0,
700 | "Plans": [
701 | {
702 | "Node Type": "CTE Scan",
703 | "Parent Relationship": "Outer",
704 | "Parallel Aware": false,
705 | "CTE Name": "modularity_comments",
706 | "Alias": "mc",
707 | "Startup Cost": 0.00,
708 | "Total Cost": 498.54,
709 | "Plan Rows": 24927,
710 | "Plan Width": 4,
711 | "Actual Startup Time": 279.075,
712 | "Actual Total Time": 279.075,
713 | "Actual Rows": 1,
714 | "Actual Loops": 1,
715 | "Shared Hit Blocks": 985,
716 | "Shared Read Blocks": 0,
717 | "Shared Dirtied Blocks": 0,
718 | "Shared Written Blocks": 0,
719 | "Local Hit Blocks": 0,
720 | "Local Read Blocks": 0,
721 | "Local Dirtied Blocks": 0,
722 | "Local Written Blocks": 0,
723 | "Temp Read Blocks": 0,
724 | "Temp Written Blocks": 0
725 | },
726 | {
727 | "Node Type": "Hash",
728 | "Parent Relationship": "Inner",
729 | "Parallel Aware": false,
730 | "Startup Cost": 245.90,
731 | "Total Cost": 245.90,
732 | "Plan Rows": 1,
733 | "Plan Width": 41,
734 | "Actual Startup Time": 223.292,
735 | "Actual Total Time": 223.292,
736 | "Actual Rows": 0,
737 | "Actual Loops": 1,
738 | "Hash Buckets": 1024,
739 | "Original Hash Buckets": 1024,
740 | "Hash Batches": 1,
741 | "Original Hash Batches": 1,
742 | "Peak Memory Usage": 8,
743 | "Shared Hit Blocks": 987,
744 | "Shared Read Blocks": 0,
745 | "Shared Dirtied Blocks": 0,
746 | "Shared Written Blocks": 0,
747 | "Local Hit Blocks": 0,
748 | "Local Read Blocks": 0,
749 | "Local Dirtied Blocks": 0,
750 | "Local Written Blocks": 0,
751 | "Temp Read Blocks": 0,
752 | "Temp Written Blocks": 0,
753 | "Plans": [
754 | {
755 | "Node Type": "Hash Join",
756 | "Parent Relationship": "Outer",
757 | "Parallel Aware": false,
758 | "Join Type": "Inner",
759 | "Startup Cost": 127.83,
760 | "Total Cost": 245.90,
761 | "Plan Rows": 1,
762 | "Plan Width": 41,
763 | "Actual Startup Time": 223.291,
764 | "Actual Total Time": 223.291,
765 | "Actual Rows": 0,
766 | "Actual Loops": 1,
767 | "Inner Unique": false,
768 | "Hash Cond": "(sp.user_id = u.id)",
769 | "Shared Hit Blocks": 987,
770 | "Shared Read Blocks": 0,
771 | "Shared Dirtied Blocks": 0,
772 | "Shared Written Blocks": 0,
773 | "Local Hit Blocks": 0,
774 | "Local Read Blocks": 0,
775 | "Local Dirtied Blocks": 0,
776 | "Local Written Blocks": 0,
777 | "Temp Read Blocks": 0,
778 | "Temp Written Blocks": 0,
779 | "Plans": [
780 | {
781 | "Node Type": "CTE Scan",
782 | "Parent Relationship": "Outer",
783 | "Parallel Aware": false,
784 | "CTE Name": "sql_posts",
785 | "Alias": "sp",
786 | "Startup Cost": 0.00,
787 | "Total Cost": 99.42,
788 | "Plan Rows": 4971,
789 | "Plan Width": 4,
790 | "Actual Startup Time": 0.025,
791 | "Actual Total Time": 0.025,
792 | "Actual Rows": 1,
793 | "Actual Loops": 1,
794 | "Shared Hit Blocks": 1,
795 | "Shared Read Blocks": 0,
796 | "Shared Dirtied Blocks": 0,
797 | "Shared Written Blocks": 0,
798 | "Local Hit Blocks": 0,
799 | "Local Read Blocks": 0,
800 | "Local Dirtied Blocks": 0,
801 | "Local Written Blocks": 0,
802 | "Temp Read Blocks": 0,
803 | "Temp Written Blocks": 0
804 | },
805 | {
806 | "Node Type": "Hash",
807 | "Parent Relationship": "Inner",
808 | "Parallel Aware": false,
809 | "Startup Cost": 127.81,
810 | "Total Cost": 127.81,
811 | "Plan Rows": 1,
812 | "Plan Width": 37,
813 | "Actual Startup Time": 223.252,
814 | "Actual Total Time": 223.252,
815 | "Actual Rows": 0,
816 | "Actual Loops": 1,
817 | "Hash Buckets": 1024,
818 | "Original Hash Buckets": 1024,
819 | "Hash Batches": 1,
820 | "Original Hash Batches": 1,
821 | "Peak Memory Usage": 8,
822 | "Shared Hit Blocks": 986,
823 | "Shared Read Blocks": 0,
824 | "Shared Dirtied Blocks": 0,
825 | "Shared Written Blocks": 0,
826 | "Local Hit Blocks": 0,
827 | "Local Read Blocks": 0,
828 | "Local Dirtied Blocks": 0,
829 | "Local Written Blocks": 0,
830 | "Temp Read Blocks": 0,
831 | "Temp Written Blocks": 0,
832 | "Plans": [
833 | {
834 | "Node Type": "Hash Join",
835 | "Parent Relationship": "Outer",
836 | "Parallel Aware": false,
837 | "Join Type": "Inner",
838 | "Startup Cost": 67.29,
839 | "Total Cost": 127.81,
840 | "Plan Rows": 1,
841 | "Plan Width": 37,
842 | "Actual Startup Time": 223.252,
843 | "Actual Total Time": 223.252,
844 | "Actual Rows": 0,
845 | "Actual Loops": 1,
846 | "Inner Unique": false,
847 | "Hash Cond": "(dp.user_id = u.id)",
848 | "Shared Hit Blocks": 986,
849 | "Shared Read Blocks": 0,
850 | "Shared Dirtied Blocks": 0,
851 | "Shared Written Blocks": 0,
852 | "Local Hit Blocks": 0,
853 | "Local Read Blocks": 0,
854 | "Local Dirtied Blocks": 0,
855 | "Local Written Blocks": 0,
856 | "Temp Read Blocks": 0,
857 | "Temp Written Blocks": 0,
858 | "Plans": [
859 | {
860 | "Node Type": "CTE Scan",
861 | "Parent Relationship": "Outer",
862 | "Parallel Aware": false,
863 | "CTE Name": "database_posts",
864 | "Alias": "dp",
865 | "Startup Cost": 0.00,
866 | "Total Cost": 50.96,
867 | "Plan Rows": 2548,
868 | "Plan Width": 4,
869 | "Actual Startup Time": 0.011,
870 | "Actual Total Time": 0.011,
871 | "Actual Rows": 1,
872 | "Actual Loops": 1,
873 | "Shared Hit Blocks": 1,
874 | "Shared Read Blocks": 0,
875 | "Shared Dirtied Blocks": 0,
876 | "Shared Written Blocks": 0,
877 | "Local Hit Blocks": 0,
878 | "Local Read Blocks": 0,
879 | "Local Dirtied Blocks": 0,
880 | "Local Written Blocks": 0,
881 | "Temp Read Blocks": 0,
882 | "Temp Written Blocks": 0
883 | },
884 | {
885 | "Node Type": "Hash",
886 | "Parent Relationship": "Inner",
887 | "Parallel Aware": false,
888 | "Startup Cost": 67.28,
889 | "Total Cost": 67.28,
890 | "Plan Rows": 1,
891 | "Plan Width": 33,
892 | "Actual Startup Time": 223.214,
893 | "Actual Total Time": 223.214,
894 | "Actual Rows": 0,
895 | "Actual Loops": 1,
896 | "Hash Buckets": 1024,
897 | "Original Hash Buckets": 1024,
898 | "Hash Batches": 1,
899 | "Original Hash Batches": 1,
900 | "Peak Memory Usage": 8,
901 | "Shared Hit Blocks": 985,
902 | "Shared Read Blocks": 0,
903 | "Shared Dirtied Blocks": 0,
904 | "Shared Written Blocks": 0,
905 | "Local Hit Blocks": 0,
906 | "Local Read Blocks": 0,
907 | "Local Dirtied Blocks": 0,
908 | "Local Written Blocks": 0,
909 | "Temp Read Blocks": 0,
910 | "Temp Written Blocks": 0,
911 | "Plans": [
912 | {
913 | "Node Type": "Hash Join",
914 | "Parent Relationship": "Outer",
915 | "Parallel Aware": false,
916 | "Join Type": "Inner",
917 | "Startup Cost": 8.34,
918 | "Total Cost": 67.28,
919 | "Plan Rows": 1,
920 | "Plan Width": 33,
921 | "Actual Startup Time": 223.213,
922 | "Actual Total Time": 223.214,
923 | "Actual Rows": 0,
924 | "Actual Loops": 1,
925 | "Inner Unique": false,
926 | "Hash Cond": "(pp.user_id = u.id)",
927 | "Shared Hit Blocks": 985,
928 | "Shared Read Blocks": 0,
929 | "Shared Dirtied Blocks": 0,
930 | "Shared Written Blocks": 0,
931 | "Local Hit Blocks": 0,
932 | "Local Read Blocks": 0,
933 | "Local Dirtied Blocks": 0,
934 | "Local Written Blocks": 0,
935 | "Temp Read Blocks": 0,
936 | "Temp Written Blocks": 0,
937 | "Plans": [
938 | {
939 | "Node Type": "CTE Scan",
940 | "Parent Relationship": "Outer",
941 | "Parallel Aware": false,
942 | "CTE Name": "postgres_posts",
943 | "Alias": "pp",
944 | "Startup Cost": 0.00,
945 | "Total Cost": 49.62,
946 | "Plan Rows": 2481,
947 | "Plan Width": 4,
948 | "Actual Startup Time": 0.035,
949 | "Actual Total Time": 0.035,
950 | "Actual Rows": 1,
951 | "Actual Loops": 1,
952 | "Shared Hit Blocks": 1,
953 | "Shared Read Blocks": 0,
954 | "Shared Dirtied Blocks": 0,
955 | "Shared Written Blocks": 0,
956 | "Local Hit Blocks": 0,
957 | "Local Read Blocks": 0,
958 | "Local Dirtied Blocks": 0,
959 | "Local Written Blocks": 0,
960 | "Temp Read Blocks": 0,
961 | "Temp Written Blocks": 0
962 | },
963 | {
964 | "Node Type": "Hash",
965 | "Parent Relationship": "Inner",
966 | "Parallel Aware": false,
967 | "Startup Cost": 8.33,
968 | "Total Cost": 8.33,
969 | "Plan Rows": 1,
970 | "Plan Width": 29,
971 | "Actual Startup Time": 223.167,
972 | "Actual Total Time": 223.167,
973 | "Actual Rows": 0,
974 | "Actual Loops": 1,
975 | "Hash Buckets": 1024,
976 | "Original Hash Buckets": 1024,
977 | "Hash Batches": 1,
978 | "Original Hash Batches": 1,
979 | "Peak Memory Usage": 8,
980 | "Shared Hit Blocks": 984,
981 | "Shared Read Blocks": 0,
982 | "Shared Dirtied Blocks": 0,
983 | "Shared Written Blocks": 0,
984 | "Local Hit Blocks": 0,
985 | "Local Read Blocks": 0,
986 | "Local Dirtied Blocks": 0,
987 | "Local Written Blocks": 0,
988 | "Temp Read Blocks": 0,
989 | "Temp Written Blocks": 0,
990 | "Plans": [
991 | {
992 | "Node Type": "Nested Loop",
993 | "Parent Relationship": "Outer",
994 | "Parallel Aware": false,
995 | "Join Type": "Inner",
996 | "Startup Cost": 0.29,
997 | "Total Cost": 8.33,
998 | "Plan Rows": 1,
999 | "Plan Width": 29,
1000 | "Actual Startup Time": 223.166,
1001 | "Actual Total Time": 223.166,
1002 | "Actual Rows": 0,
1003 | "Actual Loops": 1,
1004 | "Inner Unique": true,
1005 | "Shared Hit Blocks": 984,
1006 | "Shared Read Blocks": 0,
1007 | "Shared Dirtied Blocks": 0,
1008 | "Shared Written Blocks": 0,
1009 | "Local Hit Blocks": 0,
1010 | "Local Read Blocks": 0,
1011 | "Local Dirtied Blocks": 0,
1012 | "Local Written Blocks": 0,
1013 | "Temp Read Blocks": 0,
1014 | "Temp Written Blocks": 0,
1015 | "Plans": [
1016 | {
1017 | "Node Type": "CTE Scan",
1018 | "Parent Relationship": "Outer",
1019 | "Parallel Aware": false,
1020 | "CTE Name": "performance_comments",
1021 | "Alias": "pc",
1022 | "Startup Cost": 0.00,
1023 | "Total Cost": 0.02,
1024 | "Plan Rows": 1,
1025 | "Plan Width": 4,
1026 | "Actual Startup Time": 223.166,
1027 | "Actual Total Time": 223.166,
1028 | "Actual Rows": 0,
1029 | "Actual Loops": 1,
1030 | "Shared Hit Blocks": 984,
1031 | "Shared Read Blocks": 0,
1032 | "Shared Dirtied Blocks": 0,
1033 | "Shared Written Blocks": 0,
1034 | "Local Hit Blocks": 0,
1035 | "Local Read Blocks": 0,
1036 | "Local Dirtied Blocks": 0,
1037 | "Local Written Blocks": 0,
1038 | "Temp Read Blocks": 0,
1039 | "Temp Written Blocks": 0
1040 | },
1041 | {
1042 | "Node Type": "Index Scan",
1043 | "Parent Relationship": "Inner",
1044 | "Parallel Aware": false,
1045 | "Scan Direction": "Forward",
1046 | "Index Name": "users_pkey",
1047 | "Relation Name": "users",
1048 | "Alias": "u",
1049 | "Startup Cost": 0.29,
1050 | "Total Cost": 8.31,
1051 | "Plan Rows": 1,
1052 | "Plan Width": 25,
1053 | "Actual Startup Time": 0.000,
1054 | "Actual Total Time": 0.000,
1055 | "Actual Rows": 0,
1056 | "Actual Loops": 0,
1057 | "Index Cond": "(id = pc.user_id)",
1058 | "Rows Removed by Index Recheck": 0,
1059 | "Shared Hit Blocks": 0,
1060 | "Shared Read Blocks": 0,
1061 | "Shared Dirtied Blocks": 0,
1062 | "Shared Written Blocks": 0,
1063 | "Local Hit Blocks": 0,
1064 | "Local Read Blocks": 0,
1065 | "Local Dirtied Blocks": 0,
1066 | "Local Written Blocks": 0,
1067 | "Temp Read Blocks": 0,
1068 | "Temp Written Blocks": 0
1069 | }
1070 | ]
1071 | }
1072 | ]
1073 | }
1074 | ]
1075 | }
1076 | ]
1077 | }
1078 | ]
1079 | }
1080 | ]
1081 | }
1082 | ]
1083 | }
1084 | ]
1085 | }
1086 | ]
1087 | }
1088 | ]
1089 | }
1090 | ]
1091 | }
1092 | ]
1093 | },
1094 | {
1095 | "Node Type": "Sort",
1096 | "Parent Relationship": "Inner",
1097 | "Parallel Aware": false,
1098 | "Startup Cost": 1.08,
1099 | "Total Cost": 1.14,
1100 | "Plan Rows": 25,
1101 | "Plan Width": 4,
1102 | "Actual Startup Time": 0.000,
1103 | "Actual Total Time": 0.000,
1104 | "Actual Rows": 0,
1105 | "Actual Loops": 0,
1106 | "Sort Key": ["egu.id"],
1107 | "Shared Hit Blocks": 0,
1108 | "Shared Read Blocks": 0,
1109 | "Shared Dirtied Blocks": 0,
1110 | "Shared Written Blocks": 0,
1111 | "Local Hit Blocks": 0,
1112 | "Local Read Blocks": 0,
1113 | "Local Dirtied Blocks": 0,
1114 | "Local Written Blocks": 0,
1115 | "Temp Read Blocks": 0,
1116 | "Temp Written Blocks": 0,
1117 | "Plans": [
1118 | {
1119 | "Node Type": "CTE Scan",
1120 | "Parent Relationship": "Outer",
1121 | "Parallel Aware": false,
1122 | "CTE Name": "early_gmail_users",
1123 | "Alias": "egu",
1124 | "Startup Cost": 0.00,
1125 | "Total Cost": 0.50,
1126 | "Plan Rows": 25,
1127 | "Plan Width": 4,
1128 | "Actual Startup Time": 0.000,
1129 | "Actual Total Time": 0.000,
1130 | "Actual Rows": 0,
1131 | "Actual Loops": 0,
1132 | "Shared Hit Blocks": 0,
1133 | "Shared Read Blocks": 0,
1134 | "Shared Dirtied Blocks": 0,
1135 | "Shared Written Blocks": 0,
1136 | "Local Hit Blocks": 0,
1137 | "Local Read Blocks": 0,
1138 | "Local Dirtied Blocks": 0,
1139 | "Local Written Blocks": 0,
1140 | "Temp Read Blocks": 0,
1141 | "Temp Written Blocks": 0
1142 | }
1143 | ]
1144 | }
1145 | ]
1146 | },
1147 | {
1148 | "Node Type": "Hash Join",
1149 | "Parent Relationship": "Inner",
1150 | "Parallel Aware": false,
1151 | "Join Type": "Inner",
1152 | "Startup Cost": 0.52,
1153 | "Total Cost": 2.01,
1154 | "Plan Rows": 16,
1155 | "Plan Width": 8,
1156 | "Actual Startup Time": 0.000,
1157 | "Actual Total Time": 0.000,
1158 | "Actual Rows": 0,
1159 | "Actual Loops": 0,
1160 | "Inner Unique": false,
1161 | "Hash Cond": "(ehu.id = eyu.id)",
1162 | "Shared Hit Blocks": 0,
1163 | "Shared Read Blocks": 0,
1164 | "Shared Dirtied Blocks": 0,
1165 | "Shared Written Blocks": 0,
1166 | "Local Hit Blocks": 0,
1167 | "Local Read Blocks": 0,
1168 | "Local Dirtied Blocks": 0,
1169 | "Local Written Blocks": 0,
1170 | "Temp Read Blocks": 0,
1171 | "Temp Written Blocks": 0,
1172 | "Plans": [
1173 | {
1174 | "Node Type": "CTE Scan",
1175 | "Parent Relationship": "Outer",
1176 | "Parallel Aware": false,
1177 | "CTE Name": "early_hotmail_users",
1178 | "Alias": "ehu",
1179 | "Startup Cost": 0.00,
1180 | "Total Cost": 1.12,
1181 | "Plan Rows": 56,
1182 | "Plan Width": 4,
1183 | "Actual Startup Time": 0.000,
1184 | "Actual Total Time": 0.000,
1185 | "Actual Rows": 0,
1186 | "Actual Loops": 0,
1187 | "Shared Hit Blocks": 0,
1188 | "Shared Read Blocks": 0,
1189 | "Shared Dirtied Blocks": 0,
1190 | "Shared Written Blocks": 0,
1191 | "Local Hit Blocks": 0,
1192 | "Local Read Blocks": 0,
1193 | "Local Dirtied Blocks": 0,
1194 | "Local Written Blocks": 0,
1195 | "Temp Read Blocks": 0,
1196 | "Temp Written Blocks": 0
1197 | },
1198 | {
1199 | "Node Type": "Hash",
1200 | "Parent Relationship": "Inner",
1201 | "Parallel Aware": false,
1202 | "Startup Cost": 0.32,
1203 | "Total Cost": 0.32,
1204 | "Plan Rows": 16,
1205 | "Plan Width": 4,
1206 | "Actual Startup Time": 0.000,
1207 | "Actual Total Time": 0.000,
1208 | "Actual Rows": 0,
1209 | "Actual Loops": 0,
1210 | "Shared Hit Blocks": 0,
1211 | "Shared Read Blocks": 0,
1212 | "Shared Dirtied Blocks": 0,
1213 | "Shared Written Blocks": 0,
1214 | "Local Hit Blocks": 0,
1215 | "Local Read Blocks": 0,
1216 | "Local Dirtied Blocks": 0,
1217 | "Local Written Blocks": 0,
1218 | "Temp Read Blocks": 0,
1219 | "Temp Written Blocks": 0,
1220 | "Plans": [
1221 | {
1222 | "Node Type": "CTE Scan",
1223 | "Parent Relationship": "Outer",
1224 | "Parallel Aware": false,
1225 | "CTE Name": "early_yahoo_users",
1226 | "Alias": "eyu",
1227 | "Startup Cost": 0.00,
1228 | "Total Cost": 0.32,
1229 | "Plan Rows": 16,
1230 | "Plan Width": 4,
1231 | "Actual Startup Time": 0.000,
1232 | "Actual Total Time": 0.000,
1233 | "Actual Rows": 0,
1234 | "Actual Loops": 0,
1235 | "Shared Hit Blocks": 0,
1236 | "Shared Read Blocks": 0,
1237 | "Shared Dirtied Blocks": 0,
1238 | "Shared Written Blocks": 0,
1239 | "Local Hit Blocks": 0,
1240 | "Local Read Blocks": 0,
1241 | "Local Dirtied Blocks": 0,
1242 | "Local Written Blocks": 0,
1243 | "Temp Read Blocks": 0,
1244 | "Temp Written Blocks": 0
1245 | }
1246 | ]
1247 | }
1248 | ]
1249 | }
1250 | ]
1251 | }
1252 | ]
1253 | },
1254 | "Planning Time": 20.603,
1255 | "Triggers": [
1256 | ],
1257 | "Execution Time": 756.376
1258 | }
1259 | ]
1260 |
--------------------------------------------------------------------------------
/docs/cte_flamegraph.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
56 |
57 | pg_flame
58 |
59 |
60 |
61 |
62 |
63 |
64 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
149 |
150 |
151 |
--------------------------------------------------------------------------------