pghero 2.0.2 → 2.0.3

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of pghero might be problematic. Click here for more details.

checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 1a1b8fd1b842ba05d906e6e8881f660666272df2
4
- data.tar.gz: baf28af591b300f743afff313dc4065a9dc79016
3
+ metadata.gz: a1a3cb7c5c2090aa6b4dcc0fb11aca000945a5a4
4
+ data.tar.gz: 2304979bb7676c7a346bfbd490e697f16379f8bb
5
5
  SHA512:
6
- metadata.gz: 679f9d8cc6560727236cedb2f5dacb5030efacb418973683345d904fe3d0abcab12376c1d27b187100d9a921391f8651ff9cd26f4505115968fd203883ff97be
7
- data.tar.gz: 77c3f3cabd0d818f266ce433a9ce2e450fa3dd8201c969b199ffd33c1d5e445117ce05f816087fb5ae046762d236fe48b7d9d3c0543ad659827f81be381c1537
6
+ metadata.gz: cb6cc9c80f2ea049225b3f8d4da5eefb7d3ac754a33ba6da644fff7adbb385626f4f5967fb9e91bb3328575d42e52a064c9d7d5cef43273b8d7ac894155c4197
7
+ data.tar.gz: 964c90c704e2049d3d2a47cad1479146409a0ad49ffa7a1436dc913ac8cbb992dd101cf3021ba288dbfc45736bd2c3b4f687627fbd9b5373fe24bb54cb631a5e
@@ -1,3 +1,9 @@
1
+ ## 2.0.3
2
+
3
+ - Added SQL to recreate invalid indexes
4
+ - Added unused index marker to Space page
5
+ - Fixed `capture_query_stats` on Postgres < 9.4
6
+
1
7
  ## 2.0.2
2
8
 
3
9
  - Fixed error with suggested indexes
@@ -475,6 +475,12 @@ body {
475
475
  font-weight: bold;
476
476
  }
477
477
 
478
+ .primary-key {
479
+ color: #f0ad4e;
480
+ font-size: 11px;
481
+ font-weight: bold;
482
+ }
483
+
478
484
  .origin {
479
485
  word-break: break-word;
480
486
  }
@@ -76,7 +76,8 @@ module PgHero
76
76
  end
77
77
  end
78
78
 
79
- @unused_indexes = @database.unused_indexes(max_scans: 0)
79
+ across = params[:across].to_s.split(",")
80
+ @unused_indexes = @database.unused_indexes(max_scans: 0, across: across)
80
81
  @unused_index_names = Set.new(@unused_indexes.map { |r| r[:index] })
81
82
  @show_migrations = PgHero.show_migrations
82
83
  @system_stats_enabled = @database.system_stats_enabled?
@@ -4,6 +4,7 @@
4
4
  <title><%= [@databases.size > 1 ? @database.name : "PgHero", @title].compact.join(" / ") %></title>
5
5
 
6
6
  <meta charset="utf-8" />
7
+ <%= favicon_link_tag "pghero/favicon.png" %>
7
8
  <%= stylesheet_link_tag "pghero/application" %>
8
9
  <%= javascript_include_tag "pghero/application" %>
9
10
  </head>
@@ -50,7 +50,7 @@
50
50
  &middot;
51
51
  <% end %>
52
52
  <% end %>
53
- <% if @show_details %>
53
+ <% if @show_details && query[:query_hash] %>
54
54
  <%= link_to "details", show_query_path(query[:query_hash]), target: "_blank" %>
55
55
  <% end %>
56
56
  </span>
@@ -247,7 +247,18 @@
247
247
  <tbody>
248
248
  <% @invalid_indexes.each do |index| %>
249
249
  <tr>
250
- <td><%= index[:name] %></td>
250
+ <td>
251
+ <%= index[:name] %>
252
+ <% if index[:schema] != "public" %>
253
+ <span class="text-muted"><%= query[:schema] %></span>
254
+ <% end %>
255
+ </td>
256
+ </tr>
257
+ <tr>
258
+ <td style="border-top: none; padding: 0;">
259
+ <pre><code>DROP INDEX CONCURRENTLY <%= pghero_pretty_ident(index[:name], schema: index[:schema]) %>;
260
+ <%= index[:definition].sub("CREATE INDEX ", "CREATE INDEX CONCURRENTLY ") %>;</code></pre>
261
+ </td>
251
262
  </tr>
252
263
  <% end %>
253
264
  </tbody>
@@ -34,11 +34,14 @@ ALTER INDEX new_index RENAME TO index;</code></pre>
34
34
  <tr>
35
35
  <td>
36
36
  <span style="word-break: break-all;"><%= index[:index] %></span>
37
+ <% if index[:primary] %>
38
+ <span class="primary-key">PRIMARY</span>
39
+ <% end %>
37
40
  </td>
38
41
  <td><%= PgHero.pretty_size(index[:bloat_bytes]) %></td>
39
42
  <td><%= PgHero.pretty_size(index[:index_bytes]) %></td>
40
43
  </tr>
41
- <% if @show_sql %>
44
+ <% if @show_sql && !index[:primary] %>
42
45
  <tr>
43
46
  <td colspan="3" style="border-top: none; padding: 0;">
44
47
  <% new_index = "new_#{index[:index]}".first(63) %>
@@ -32,7 +32,7 @@
32
32
  <div id="migration" style="display: none;">
33
33
  <pre>rails g migration remove_unused_indexes</pre>
34
34
  <p>And paste</p>
35
- <pre style="overflow: scroll; white-space: pre; word-break: normal;"><% @unused_indexes.sort_by { |q| q[:index] }.each do |query| %>
35
+ <pre style="overflow: scroll; white-space: pre; word-break: normal;"><% @unused_indexes.sort_by { |q| [-q[:size_bytes], q[:index]] }.each do |query| %>
36
36
  remove_index <%= query[:table].to_sym.inspect %>, name: <%= query[:index].to_s.inspect %><% end %></pre>
37
37
  </div>
38
38
  <% end %>
@@ -62,7 +62,7 @@ remove_index <%= query[:table].to_sym.inspect %>, name: <%= query[:index].to_s.i
62
62
  <% if query[:schema] != "public" %>
63
63
  <span class="text-muted"><%= query[:schema] %></span>
64
64
  <% end %>
65
- <% if @unused_index_names.include?(query[:name]) %>
65
+ <% if @unused_index_names.include?(query[:relation]) %>
66
66
  <span class="unused-index">UNUSED</span>
67
67
  <% end %>
68
68
  </td>
@@ -26,8 +26,8 @@ CREATE TABLE "pghero_query_stats" (
26
26
  "total_time" float,
27
27
  "calls" bigint,
28
28
  "captured_at" timestamp
29
- )
30
- CREATE INDEX ON "pghero_query_stats" ("database", "captured_at")
29
+ );
30
+ CREATE INDEX ON "pghero_query_stats" ("database", "captured_at");
31
31
  ```
32
32
 
33
33
  Schedule the task below to run every 5 minutes.
@@ -50,8 +50,8 @@ CREATE TABLE "pghero_space_stats" (
50
50
  "relation" text,
51
51
  "size" bigint,
52
52
  "captured_at" timestamp
53
- )
54
- CREATE INDEX ON "pghero_space_stats" ("database", "captured_at")
53
+ );
54
+ CREATE INDEX ON "pghero_space_stats" ("database", "captured_at");
55
55
  ```
56
56
 
57
57
  Schedule the task below to run once a day.
@@ -60,6 +60,18 @@ Schedule the task below to run once a day.
60
60
  docker run -ti -e DATABASE_URL=... ankane/pghero bin/rake pghero:capture_space_stats
61
61
  ```
62
62
 
63
+ ## Multiple Databases
64
+
65
+ Create a file at `/app/config/pghero.yml` with:
66
+
67
+ ```yml
68
+ databases:
69
+ primary:
70
+ url: postgres://...
71
+ replica:
72
+ url: postgres://...
73
+ ```
74
+
63
75
  ## Credits
64
76
 
65
77
  Thanks to [Brian Morton](https://github.com/bmorton) for the [original Docker image](https://github.com/bmorton/pghero_solo).
@@ -1,82 +1,73 @@
1
1
  # PgHero for Linux
2
2
 
3
- Packaged for:
3
+ Distributions
4
4
 
5
- - Ubuntu 16.04 (Xenial)
6
- - Ubuntu 14.04 (Trusty)
7
- - Ubuntu 12.04 (Precise)
8
- - Debian 7 (Wheezy)
9
- - Debian 8 (Jesse)
10
- - CentOS / RHEL 7
11
- - SUSE Linux Enterprise Server 12
5
+ - [Ubuntu 16.04 (Xenial)](#ubuntu-1604-xenial)
6
+ - [Ubuntu 14.04 (Trusty)](#ubuntu-1404-trusty)
7
+ - [Debian 8 (Jesse)](#debian-8-jesse)
8
+ - [Debian 7 (Wheezy)](#debian-7-wheezy)
9
+ - [CentOS / RHEL 7](#centos--rhel-7)
10
+ - [SUSE Linux Enterprise Server 12](#suse-linux-enterprise-server-12)
12
11
 
13
12
  64-bit only
14
13
 
15
14
  ## Installation
16
15
 
17
- Ubuntu 16.04 (Xenial)
16
+ ### Ubuntu 16.04 (Xenial)
18
17
 
19
18
  ```sh
20
- wget -qO - https://deb.packager.io/key | sudo apt-key add -
21
- echo "deb https://deb.packager.io/gh/pghero/pghero xenial master" | sudo tee /etc/apt/sources.list.d/pghero.list
19
+ wget -qO- https://dl.packager.io/srv/pghero/pghero/key | sudo apt-key add -
20
+ sudo wget -O /etc/apt/sources.list.d/pghero.list \
21
+ https://dl.packager.io/srv/pghero/pghero/master/installer/ubuntu/16.04.repo
22
22
  sudo apt-get update
23
23
  sudo apt-get -y install pghero
24
24
  ```
25
25
 
26
- Ubuntu 14.04 (Trusty)
26
+ ### Ubuntu 14.04 (Trusty)
27
27
 
28
28
  ```sh
29
- wget -qO - https://deb.packager.io/key | sudo apt-key add -
30
- echo "deb https://deb.packager.io/gh/pghero/pghero trusty master" | sudo tee /etc/apt/sources.list.d/pghero.list
29
+ wget -qO- https://dl.packager.io/srv/pghero/pghero/key | sudo apt-key add -
30
+ sudo wget -O /etc/apt/sources.list.d/pghero.list \
31
+ https://dl.packager.io/srv/pghero/pghero/master/installer/ubuntu/14.04.repo
31
32
  sudo apt-get update
32
33
  sudo apt-get -y install pghero
33
34
  ```
34
35
 
35
- Ubuntu 12.04 (Precise)
36
-
37
- ```sh
38
- wget -qO - https://deb.packager.io/key | sudo apt-key add -
39
- echo "deb https://deb.packager.io/gh/pghero/pghero precise master" | sudo tee /etc/apt/sources.list.d/pghero.list
40
- sudo apt-get update
41
- sudo apt-get -y install pghero
42
- ```
43
-
44
- Debian 7 (Wheezy)
36
+ ### Debian 8 (Jesse)
45
37
 
46
38
  ```sh
47
39
  sudo apt-get -y install apt-transport-https
48
- wget -qO - https://deb.packager.io/key | sudo apt-key add -
49
- echo "deb https://deb.packager.io/gh/pghero/pghero wheezy master" | sudo tee /etc/apt/sources.list.d/pghero.list
40
+ wget -qO- https://dl.packager.io/srv/pghero/pghero/key | sudo apt-key add -
41
+ sudo wget -O /etc/apt/sources.list.d/pghero.list \
42
+ https://dl.packager.io/srv/pghero/pghero/master/installer/debian/8.repo
50
43
  sudo apt-get update
51
44
  sudo apt-get -y install pghero
52
45
  ```
53
46
 
54
- Debian 8 (Jesse)
47
+ ### Debian 7 (Wheezy)
55
48
 
56
49
  ```sh
57
50
  sudo apt-get -y install apt-transport-https
58
- wget -qO - https://deb.packager.io/key | sudo apt-key add -
59
- echo "deb https://deb.packager.io/gh/pghero/pghero jessie master" | sudo tee /etc/apt/sources.list.d/pghero.list
51
+ wget -qO- https://dl.packager.io/srv/pghero/pghero/key | sudo apt-key add -
52
+ sudo wget -O /etc/apt/sources.list.d/pghero.list \
53
+ https://dl.packager.io/srv/pghero/pghero/master/installer/debian/7.repo
60
54
  sudo apt-get update
61
55
  sudo apt-get -y install pghero
62
56
  ```
63
57
 
64
- CentOS / RHEL 7
58
+ ### CentOS / RHEL 7
65
59
 
66
60
  ```sh
67
- sudo rpm --import https://rpm.packager.io/key
68
- echo "[pghero]
69
- name=Repository for pghero/pghero application.
70
- baseurl=https://rpm.packager.io/gh/pghero/pghero/centos7/master
71
- enabled=1" | sudo tee /etc/yum.repos.d/pghero.repo
61
+ sudo wget -O /etc/yum.repos.d/pghero.repo \
62
+ https://dl.packager.io/srv/pghero/pghero/master/installer/el/7.repo
72
63
  sudo yum -y install pghero
73
64
  ```
74
65
 
75
- SUSE Linux Enterprise Server 12
66
+ ### SUSE Linux Enterprise Server 12
76
67
 
77
68
  ```sh
78
- sudo rpm --import https://rpm.packager.io/key
79
- sudo zypper addrepo "https://rpm.packager.io/gh/pghero/pghero/sles12/master" "pghero"
69
+ sudo wget -O /etc/zypp/repos.d/pghero.repo \
70
+ https://dl.packager.io/srv/pghero/pghero/master/installer/sles/12.repo
80
71
  sudo zypper install pghero
81
72
  ```
82
73
 
@@ -158,8 +149,8 @@ CREATE TABLE "pghero_query_stats" (
158
149
  "total_time" float,
159
150
  "calls" bigint,
160
151
  "captured_at" timestamp
161
- )
162
- CREATE INDEX ON "pghero_query_stats" ("database", "captured_at")
152
+ );
153
+ CREATE INDEX ON "pghero_query_stats" ("database", "captured_at");
163
154
  ```
164
155
 
165
156
  This table can be in the current database or another database. If another database, run:
@@ -188,8 +179,8 @@ CREATE TABLE "pghero_space_stats" (
188
179
  "relation" text,
189
180
  "size" bigint,
190
181
  "captured_at" timestamp
191
- )
192
- CREATE INDEX ON "pghero_space_stats" ("database", "captured_at")
182
+ );
183
+ CREATE INDEX ON "pghero_space_stats" ("database", "captured_at");
193
184
  ```
194
185
 
195
186
  Schedule the task below to run once a day.
@@ -212,12 +203,11 @@ sudo pghero config:set PGHERO_DB_INSTANCE_IDENTIFIER=epona
212
203
  Create a `pghero.yml` with:
213
204
 
214
205
  ```yml
215
- production:
216
- databases:
217
- primary:
218
- url: postgres://...
219
- replica:
220
- url: postgres://...
206
+ databases:
207
+ primary:
208
+ url: postgres://...
209
+ replica:
210
+ url: postgres://...
221
211
  ```
222
212
 
223
213
  And run:
@@ -260,6 +250,7 @@ Ubuntu and Debian
260
250
  ```sh
261
251
  sudo apt-get update
262
252
  sudo apt-get install --only-upgrade pghero
253
+ sudo service pghero restart
263
254
  ```
264
255
 
265
256
  CentOS and RHEL
@@ -267,12 +258,14 @@ CentOS and RHEL
267
258
  ```sh
268
259
  sudo yum update
269
260
  sudo yum install pghero
261
+ sudo service pghero restart
270
262
  ```
271
263
 
272
264
  SUSE
273
265
 
274
266
  ```sh
275
267
  sudo zypper update pghero
268
+ sudo service pghero restart
276
269
  ```
277
270
 
278
271
  ## Credits
@@ -118,18 +118,11 @@ PGHERO_DB_INSTANCE_IDENTIFIER=epona
118
118
  Create `config/pghero.yml` with:
119
119
 
120
120
  ```yml
121
- default: &default
122
- databases:
123
- primary:
124
- url: <%= ENV["PGHERO_DATABASE_URL"] %>
125
- replica:
126
- url: <%= ENV["REPLICA_DATABASE_URL"] %>
127
-
128
- development:
129
- <<: *default
130
-
131
- production:
132
- <<: *default
121
+ databases:
122
+ primary:
123
+ url: <%= ENV["PGHERO_DATABASE_URL"] %>
124
+ replica:
125
+ url: <%= ENV["REPLICA_DATABASE_URL"] %>
133
126
  ```
134
127
 
135
128
  ## Customize
@@ -26,7 +26,8 @@ require "pghero/connection"
26
26
  require "pghero/query_stats"
27
27
 
28
28
  module PgHero
29
- class NotEnabled < StandardError; end
29
+ class Error < StandardError; end
30
+ class NotEnabled < Error; end
30
31
 
31
32
  # settings
32
33
  class << self
@@ -68,8 +68,8 @@ module PgHero
68
68
  SQL
69
69
  end
70
70
 
71
- def unused_indexes(max_scans: 50)
72
- select_all_size <<-SQL
71
+ def unused_indexes(max_scans: 50, across: [])
72
+ result = select_all_size <<-SQL
73
73
  SELECT
74
74
  schemaname AS schema,
75
75
  relname AS table,
@@ -87,6 +87,15 @@ module PgHero
87
87
  pg_relation_size(i.indexrelid) DESC,
88
88
  relname ASC
89
89
  SQL
90
+
91
+ across.each do |database_id|
92
+ database = PgHero.databases.values.find { |d| d.id == database_id }
93
+ raise PgHero::Error, "Database not found: #{database_id}" unless database
94
+ across_result = Set.new(database.unused_indexes(max_scans: max_scans).map { |v| [v[:schema], v[:index]] })
95
+ result.select! { |v| across_result.include?([v[:schema], v[:index]]) }
96
+ end
97
+
98
+ result
90
99
  end
91
100
 
92
101
  def reset_stats
@@ -108,7 +117,9 @@ module PgHero
108
117
  def invalid_indexes
109
118
  select_all <<-SQL
110
119
  SELECT
111
- c.relname AS index
120
+ n.nspname AS schema,
121
+ c.relname AS index,
122
+ pg_get_indexdef(i.indexrelid) AS definition
112
123
  FROM
113
124
  pg_catalog.pg_class c,
114
125
  pg_catalog.pg_namespace n,
@@ -297,9 +308,12 @@ module PgHero
297
308
  index_name AS index,
298
309
  wastedbytes AS bloat_bytes,
299
310
  totalbytes AS index_bytes,
300
- pg_get_indexdef(indexrelid) AS definition
311
+ pg_get_indexdef(rb.indexrelid) AS definition,
312
+ indisprimary AS primary
301
313
  FROM
302
- raw_bloat
314
+ raw_bloat rb
315
+ INNER JOIN
316
+ pg_index i ON i.indexrelid = rb.indexrelid
303
317
  WHERE
304
318
  wastedbytes >= #{min_size.to_i}
305
319
  ORDER BY
@@ -103,6 +103,8 @@ module PgHero
103
103
  query_stats[database_id] = query_stats(limit: 1000000, database: database_name)
104
104
  end
105
105
 
106
+ supports_query_hash = supports_query_hash?
107
+
106
108
  if query_stats.any? { |_, v| v.any? } && reset_query_stats
107
109
  query_stats.each do |db_id, db_query_stats|
108
110
  if db_query_stats.any?
@@ -114,7 +116,7 @@ module PgHero
114
116
  qs[:total_minutes] * 60 * 1000,
115
117
  qs[:calls],
116
118
  now,
117
- qs[:query_hash],
119
+ supports_query_hash ? qs[:query_hash] : nil,
118
120
  qs[:user]
119
121
  ]
120
122
  end
@@ -1,3 +1,3 @@
1
1
  module PgHero
2
- VERSION = "2.0.2"
2
+ VERSION = "2.0.3"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pghero
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.2
4
+ version: 2.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrew Kane
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-08-09 00:00:00.000000000 Z
11
+ date: 2017-08-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -122,6 +122,7 @@ files:
122
122
  - LICENSE.txt
123
123
  - README.md
124
124
  - Rakefile
125
+ - app/assets/images/pghero/favicon.png
125
126
  - app/assets/javascripts/pghero/Chart.bundle.js
126
127
  - app/assets/javascripts/pghero/application.js
127
128
  - app/assets/javascripts/pghero/chartkick.js