ruby-pg-extras 1.2.0 → 1.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.circleci/config.yml +2 -1
- data/README.md +43 -14
- data/lib/ruby-pg-extras.rb +16 -5
- data/lib/ruby-pg-extras/queries/calls.sql +3 -3
- data/lib/ruby-pg-extras/queries/long_running_queries.sql +1 -1
- data/lib/ruby-pg-extras/queries/outliers.sql +3 -3
- data/lib/ruby-pg-extras/queries/table_indexes_size.sql +1 -1
- data/lib/ruby-pg-extras/queries/table_size.sql +1 -1
- data/lib/ruby-pg-extras/queries/unused_indexes.sql +1 -1
- data/lib/ruby-pg-extras/version.rb +3 -1
- metadata +6 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5d6fbc5ab6b75d6afab360ce585c6b99da6f7c7622da5c7d41ef5c9a352cf1d0
|
4
|
+
data.tar.gz: d6065e2b079138d523ea47dd5855793e6c53d45d7d0f59f6035a3f0cc22e97d1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 06235baa16b1433f94c6df83cdd764792ab85217ea0dae0880fedf981f84e7e4a12748e267462bc99a69096dd7706cf6893680d24f7b1e7da5fc8c502e4bc9fb
|
7
|
+
data.tar.gz: 0cce03aa9d5e05cc826c4d4835fc4fc8c3d50f3d062dfbdd7deec85d4b51366de68e264d3e3023f509464144ab80ae983975cecb50aaf3d333b1a8e0962df878
|
data/.circleci/config.yml
CHANGED
@@ -16,7 +16,8 @@ jobs:
|
|
16
16
|
- run: gem update --system
|
17
17
|
- run: gem install bundler
|
18
18
|
- run: bundle install --path vendor/bundle
|
19
|
-
- run: sudo apt
|
19
|
+
- run: sudo apt-get update
|
20
|
+
- run: sudo apt install postgresql-client-11
|
20
21
|
- run: dockerize -wait tcp://localhost:5432 -timeout 1m
|
21
22
|
- run:
|
22
23
|
name: Run specs
|
data/README.md
CHANGED
@@ -4,7 +4,19 @@ Ruby port of [Heroku PG Extras](https://github.com/heroku/heroku-pg-extras) with
|
|
4
4
|
|
5
5
|
Queries can be used to obtain information about a Postgres instance, that may be useful when analyzing performance issues. This includes information about locks, index usage, buffer cache hit ratios and vacuum statistics. Ruby API enables developers to easily integrate the tool into e.g. automatic monitoring tasks.
|
6
6
|
|
7
|
-
|
7
|
+
You can check out this blog post for detailed step by step tutorial on how to [optimize PostgreSQL using PG Extras library](https://pawelurbanek.com/postgresql-fix-performance).
|
8
|
+
|
9
|
+
Alternative versions:
|
10
|
+
|
11
|
+
- [Ruby on Rails](https://github.com/pawurb/rails-pg-extras)
|
12
|
+
|
13
|
+
- [NodeJS](https://github.com/pawurb/node-postgres-extras)
|
14
|
+
|
15
|
+
- [Elixir](https://github.com/pawurb/ecto_psql_extras)
|
16
|
+
|
17
|
+
- [Python](https://github.com/pawurb/python-pg-extras)
|
18
|
+
|
19
|
+
- [Haskell](https://github.com/pawurb/haskell-pg-extras)
|
8
20
|
|
9
21
|
## Installation
|
10
22
|
|
@@ -14,6 +26,19 @@ In your Gemfile
|
|
14
26
|
gem "ruby-pg-extras"
|
15
27
|
```
|
16
28
|
|
29
|
+
Some of the queries (e.g., `calls` and `outliers`) require [pg_stat_statements](https://www.postgresql.org/docs/current/pgstatstatements.html) extension enabled.
|
30
|
+
|
31
|
+
You can check if it is enabled in your database by running:
|
32
|
+
|
33
|
+
```ruby
|
34
|
+
RubyPGExtras.extensions
|
35
|
+
```
|
36
|
+
You should see the similar line in the output:
|
37
|
+
|
38
|
+
```bash
|
39
|
+
| pg_stat_statements | 1.7 | 1.7 | track execution statistics of all SQL statements executed |
|
40
|
+
```
|
41
|
+
|
17
42
|
## Usage
|
18
43
|
|
19
44
|
Gem expects the `ENV['DATABASE_URL']` value in the following format:
|
@@ -91,7 +116,7 @@ RubyPGExtras.index_cache_hit
|
|
91
116
|
(truncated results for brevity)
|
92
117
|
```
|
93
118
|
|
94
|
-
The same as `cache_hit` with each table's indexes cache hit info displayed
|
119
|
+
The same as `cache_hit` with each table's indexes cache hit info displayed separately.
|
95
120
|
|
96
121
|
### `table_cache_hit`
|
97
122
|
|
@@ -144,7 +169,7 @@ RubyPGExtras.locks
|
|
144
169
|
(4 rows)
|
145
170
|
```
|
146
171
|
|
147
|
-
This command displays queries that have taken out an
|
172
|
+
This command displays queries that have taken out an exclusive lock on a relation. Exclusive locks typically prevent other operations on that relation from taking place, and can be a cause of "hung" queries that are waiting for a lock to be granted.
|
148
173
|
|
149
174
|
### `all_locks`
|
150
175
|
|
@@ -174,7 +199,7 @@ RubyPGExtras.outliers
|
|
174
199
|
(truncated results for brevity)
|
175
200
|
```
|
176
201
|
|
177
|
-
This command displays statements, obtained from `pg_stat_statements`, ordered by the amount of time to execute in aggregate. This includes the statement itself, the total execution time for that statement, the proportion of total execution time for all statements that statement has taken up, the number of times that statement has been called, and the amount of time that statement spent on synchronous I/O (reading/writing from the
|
202
|
+
This command displays statements, obtained from `pg_stat_statements`, ordered by the amount of time to execute in aggregate. This includes the statement itself, the total execution time for that statement, the proportion of total execution time for all statements that statement has taken up, the number of times that statement has been called, and the amount of time that statement spent on synchronous I/O (reading/writing from the file system).
|
178
203
|
|
179
204
|
Typically, an efficient query will have an appropriate ratio of calls to total execution time, with as little time spent on I/O as possible. Queries that have a high total execution time but low call count should be investigated to improve their performance. Queries that have a high proportion of execution time being spent on synchronous I/O should also be investigated.
|
180
205
|
|
@@ -283,7 +308,7 @@ RubyPGExtras.table_indexes_size
|
|
283
308
|
(truncated results for brevity)
|
284
309
|
```
|
285
310
|
|
286
|
-
This command displays the total size of indexes for each table, in MB. It is
|
311
|
+
This command displays the total size of indexes for each table and materialized view, in MB. It is calculated by using the system administration function `pg_indexes_size()`.
|
287
312
|
|
288
313
|
### `total_table_size`
|
289
314
|
|
@@ -301,7 +326,7 @@ RubyPGExtras.total_table_size
|
|
301
326
|
(truncated results for brevity)
|
302
327
|
```
|
303
328
|
|
304
|
-
This command displays the total size of each table in the database, in MB. It is calculated by using the system administration function `pg_total_relation_size()`, which includes table size, total index size and TOAST data.
|
329
|
+
This command displays the total size of each table and materialized view in the database, in MB. It is calculated by using the system administration function `pg_total_relation_size()`, which includes table size, total index size and TOAST data.
|
305
330
|
|
306
331
|
### `unused_indexes`
|
307
332
|
|
@@ -339,7 +364,7 @@ RubyPGExtras.seq_scans
|
|
339
364
|
(truncated results for brevity)
|
340
365
|
```
|
341
366
|
|
342
|
-
This command displays the number of sequential scans recorded against all tables, descending by count of sequential scans. Tables that have very high numbers of sequential scans may be
|
367
|
+
This command displays the number of sequential scans recorded against all tables, descending by count of sequential scans. Tables that have very high numbers of sequential scans may be under-indexed, and it may be worth investigating queries that read from these tables.
|
343
368
|
|
344
369
|
### `long_running_queries`
|
345
370
|
|
@@ -412,7 +437,7 @@ RubyPGExtras.vacuum_stats
|
|
412
437
|
(truncated results for brevity)
|
413
438
|
```
|
414
439
|
|
415
|
-
This command displays statistics related to vacuum operations for each table, including an
|
440
|
+
This command displays statistics related to vacuum operations for each table, including an estimation of dead rows, last autovacuum and the current autovacuum threshold. This command can be useful when determining if current vacuum thresholds require adjustments, and to determine when the table was last vacuumed.
|
416
441
|
|
417
442
|
### `kill_all`
|
418
443
|
|
@@ -424,18 +449,22 @@ RubyPGExtras.kill_all
|
|
424
449
|
|
425
450
|
This commands kills all the currently active connections to the database. It can be useful as a last resort when your database is stuck in a deadlock.
|
426
451
|
|
427
|
-
### `
|
452
|
+
### `extensions`
|
428
453
|
|
429
454
|
```ruby
|
430
455
|
|
431
|
-
RubyPGExtras.
|
456
|
+
RubyPGExtras.extensions
|
432
457
|
|
433
458
|
```
|
434
459
|
|
435
|
-
This command
|
460
|
+
This command lists all the currently installed and available PostgreSQL extensions.
|
461
|
+
|
462
|
+
### `mandelbrot`
|
463
|
+
|
464
|
+
```ruby
|
436
465
|
|
437
|
-
|
466
|
+
RubyPGExtras.mandelbrot
|
438
467
|
|
439
|
-
|
468
|
+
```
|
440
469
|
|
441
|
-
|
470
|
+
This command outputs the Mandelbrot set, calculated through SQL.
|
data/lib/ruby-pg-extras.rb
CHANGED
@@ -17,19 +17,30 @@ module RubyPGExtras
|
|
17
17
|
unused_indexes vacuum_stats kill_all
|
18
18
|
)
|
19
19
|
|
20
|
+
DEFAULT_ARGS = Hash.new({}).merge({
|
21
|
+
calls: { limit: 10 },
|
22
|
+
long_running_queries: { interval: '5 seconds' },
|
23
|
+
outliers: { limit: 10 },
|
24
|
+
unused_indexes: { min_scans: 50 }
|
25
|
+
})
|
26
|
+
|
20
27
|
QUERIES.each do |query_name|
|
21
|
-
define_singleton_method query_name do |options = {
|
28
|
+
define_singleton_method query_name do |options = {}|
|
22
29
|
run_query(
|
23
30
|
query_name: query_name,
|
24
|
-
in_format: options.fetch(:in_format)
|
31
|
+
in_format: options.fetch(:in_format, :display_table),
|
32
|
+
args: options.fetch(:args, {})
|
25
33
|
)
|
26
34
|
end
|
27
35
|
end
|
28
36
|
|
29
|
-
def self.run_query(query_name:, in_format:)
|
30
|
-
|
37
|
+
def self.run_query(query_name:, in_format:, args: {})
|
38
|
+
sql = if (custom_args = DEFAULT_ARGS[query_name].merge(args)) != {}
|
39
|
+
sql_for(query_name: query_name) % custom_args
|
40
|
+
else
|
31
41
|
sql_for(query_name: query_name)
|
32
|
-
|
42
|
+
end
|
43
|
+
result = connection.exec(sql)
|
33
44
|
|
34
45
|
display_result(
|
35
46
|
result,
|
@@ -1,9 +1,9 @@
|
|
1
|
-
/*
|
1
|
+
/* Queries that have highest frequency of execution */
|
2
2
|
|
3
3
|
SELECT query AS qry,
|
4
4
|
interval '1 millisecond' * total_time AS exec_time,
|
5
|
-
to_char((total_time/sum(total_time) OVER()) * 100, 'FM90D0') || '
|
5
|
+
to_char((total_time/sum(total_time) OVER()) * 100, 'FM90D0') || '%%' AS prop_exec_time,
|
6
6
|
to_char(calls, 'FM999G999G990') AS ncalls,
|
7
7
|
interval '1 millisecond' * (blk_read_time + blk_write_time) AS sync_io_time
|
8
8
|
FROM pg_stat_statements WHERE userid = (SELECT usesysid FROM pg_user WHERE usename = current_user LIMIT 1)
|
9
|
-
ORDER BY calls DESC LIMIT
|
9
|
+
ORDER BY calls DESC LIMIT %{limit};
|
@@ -9,6 +9,6 @@ FROM
|
|
9
9
|
WHERE
|
10
10
|
pg_stat_activity.query <> ''::text
|
11
11
|
AND state <> 'idle'
|
12
|
-
AND now() - pg_stat_activity.query_start > interval '
|
12
|
+
AND now() - pg_stat_activity.query_start > interval '%{interval}'
|
13
13
|
ORDER BY
|
14
14
|
now() - pg_stat_activity.query_start DESC;
|
@@ -1,10 +1,10 @@
|
|
1
|
-
/*
|
1
|
+
/* Queries that have longest execution time in aggregate */
|
2
2
|
|
3
3
|
SELECT interval '1 millisecond' * total_time AS total_exec_time,
|
4
|
-
to_char((total_time/sum(total_time) OVER()) * 100, 'FM90D0') || '
|
4
|
+
to_char((total_time/sum(total_time) OVER()) * 100, 'FM90D0') || '%%' AS prop_exec_time,
|
5
5
|
to_char(calls, 'FM999G999G999G990') AS ncalls,
|
6
6
|
interval '1 millisecond' * (blk_read_time + blk_write_time) AS sync_io_time,
|
7
7
|
query AS query
|
8
8
|
FROM pg_stat_statements WHERE userid = (SELECT usesysid FROM pg_user WHERE usename = current_user LIMIT 1)
|
9
9
|
ORDER BY total_time DESC
|
10
|
-
LIMIT
|
10
|
+
LIMIT %{limit};
|
@@ -11,6 +11,6 @@ SELECT
|
|
11
11
|
idx_scan as index_scans
|
12
12
|
FROM pg_stat_user_indexes ui
|
13
13
|
JOIN pg_index i ON ui.indexrelid = i.indexrelid
|
14
|
-
WHERE NOT indisunique AND idx_scan <
|
14
|
+
WHERE NOT indisunique AND idx_scan < %{min_scans} AND pg_relation_size(relid) > 5 * 8192
|
15
15
|
ORDER BY pg_relation_size(i.indexrelid) / nullif(idx_scan, 0) DESC NULLS FIRST,
|
16
16
|
pg_relation_size(i.indexrelid) DESC;
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ruby-pg-extras
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- pawurb
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-01-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: pg
|
@@ -114,7 +114,7 @@ homepage: http://github.com/pawurb/ruby-pg-extras
|
|
114
114
|
licenses:
|
115
115
|
- MIT
|
116
116
|
metadata: {}
|
117
|
-
post_install_message:
|
117
|
+
post_install_message:
|
118
118
|
rdoc_options: []
|
119
119
|
require_paths:
|
120
120
|
- lib
|
@@ -129,8 +129,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
129
129
|
- !ruby/object:Gem::Version
|
130
130
|
version: '0'
|
131
131
|
requirements: []
|
132
|
-
rubygems_version: 3.
|
133
|
-
signing_key:
|
132
|
+
rubygems_version: 3.1.4
|
133
|
+
signing_key:
|
134
134
|
specification_version: 4
|
135
135
|
summary: Ruby PostgreSQL performance database insights
|
136
136
|
test_files:
|