rails-pg-extras 4.13.0 → 5.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +47 -1
- data/lib/rails-pg-extras.rb +55 -0
- data/lib/rails_pg_extras/version.rb +1 -1
- data/spec/smoke_spec.rb +5 -0
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1f7109cdaf06d94ed2a1707fffcd477a471c84ece3e648e4279f602f27e89b67
|
4
|
+
data.tar.gz: 583b204cfad10e9c3602946d5e00d0c10eaf1a7407e7234fc1f22db154e22bab
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a3f334dcdf081777134219ab9f3c6ca0a0e95ca36495d71447690526c71bf893960219bda40d12c82973a2779131ff6977e99a141829f3a4121378b65d8e1659
|
7
|
+
data.tar.gz: 8eb2229994c72de036a4cf5e865b2503efcb831dd12c1182e4b45d43956cc89ffecb44f2bb1b7fe7a5ab50b82f4a662ddf2f7bee3756cac054d75639c8c5a6e2
|
data/README.md
CHANGED
@@ -51,7 +51,7 @@ You should see the similar line in the output:
|
|
51
51
|
RailsPgExtras.add_extensions
|
52
52
|
```
|
53
53
|
|
54
|
-
By deafult a primary ActiveRecord database connection is used for running metadata queries. To connect to a different database you can specify an `ENV['RAILS_PG_EXTRAS_DATABASE_URL']` value in the following format:
|
54
|
+
By deafult a primary ActiveRecord database connection is used for running metadata queries, rake tasks and web UI. To connect to a different database you can specify an `ENV['RAILS_PG_EXTRAS_DATABASE_URL']` value in the following format:
|
55
55
|
|
56
56
|
```ruby
|
57
57
|
ENV["RAILS_PG_EXTRAS_DATABASE_URL"] = "postgresql://postgres:secret@localhost:5432/database_name"
|
@@ -140,6 +140,52 @@ end
|
|
140
140
|
|
141
141
|
## Available methods
|
142
142
|
|
143
|
+
### `measure_queries`
|
144
|
+
|
145
|
+
This method displays query types executed when running a provided Ruby snippet, with their avg., min., max., and total duration. It also outputs info about the snippet execution duration and the portion spent running SQL queries (`total_duration`/`sql_duration`). It can help debug N+1 issues and review the impact of configuring eager loading:
|
146
|
+
|
147
|
+
```ruby
|
148
|
+
|
149
|
+
User.measure_queries { User.limit(10).map(&:team) }
|
150
|
+
|
151
|
+
# {:count=>11,
|
152
|
+
# :queries=>
|
153
|
+
# {"SELECT \"users\".* FROM \"users\" LIMIT $1"=>
|
154
|
+
# {:count=>1,
|
155
|
+
# :total_duration=>0.003183000022545457,
|
156
|
+
# :min_duration=>0.003183000022545457,
|
157
|
+
# :max_duration=>0.003183000022545457,
|
158
|
+
# :avg_duration=>0.003183000022545457},
|
159
|
+
# "SELECT \"teams\".* FROM \"teams\" WHERE \"teams\".\"id\" = $1 LIMIT $2"=>
|
160
|
+
# {:count=>10,
|
161
|
+
# :total_duration=>0.011682000011205673,
|
162
|
+
# :min_duration=>0.0007209999894257635,
|
163
|
+
# :max_duration=>0.0024030000204220414,
|
164
|
+
# :avg_duration=>0.0011682000011205673}},
|
165
|
+
# :total_duration=>0.15247199998702854,
|
166
|
+
# :sql_duration=>0.01486500003375113}
|
167
|
+
|
168
|
+
User.measure_queries { User.limit(10).includes(:team).map(&:team) }
|
169
|
+
|
170
|
+
# {:count=>2,
|
171
|
+
# :queries=>
|
172
|
+
# {"SELECT \"users\".* FROM \"users\" LIMIT $1"=>
|
173
|
+
# {:count=>1,
|
174
|
+
# :total_duration=>0.0036189999955240637,
|
175
|
+
# :min_duration=>0.0036189999955240637,
|
176
|
+
# :max_duration=>0.0036189999955240637,
|
177
|
+
# :avg_duration=>0.0036189999955240637},
|
178
|
+
# "SELECT \"teams\".* FROM \"teams\" WHERE \"teams\".\"id\" IN ($1, $2, $3, $4, $5, $6, $7, $8)"=>
|
179
|
+
# {:count=>1,
|
180
|
+
# :total_duration=>0.003714999998919666,
|
181
|
+
# :min_duration=>0.003714999998919666,
|
182
|
+
# :max_duration=>0.003714999998919666,
|
183
|
+
# :avg_duration=>0.003714999998919666}},
|
184
|
+
# :total_duration=>0.023814999993192032,
|
185
|
+
# :sql_duration=>0.0073339999944437295}
|
186
|
+
|
187
|
+
```
|
188
|
+
|
143
189
|
### `table_info`
|
144
190
|
|
145
191
|
This method displays metadata metrics for all or a selected table. You can use it to check the table's size, its cache hit metrics, and whether it is correctly indexed. Many sequential scans or no index scans are potential indicators of misconfigured indexes. This method aggregates data provided by other methods in an easy to analyze summary format.
|
data/lib/rails-pg-extras.rb
CHANGED
@@ -62,6 +62,61 @@ module RailsPgExtras
|
|
62
62
|
end
|
63
63
|
end
|
64
64
|
|
65
|
+
def self.measure_duration(&block)
|
66
|
+
starting = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
67
|
+
block.call
|
68
|
+
ending = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
69
|
+
elapsed = ending - starting
|
70
|
+
elapsed
|
71
|
+
end
|
72
|
+
|
73
|
+
def self.measure_queries(&block)
|
74
|
+
queries = {}
|
75
|
+
sql_duration = 0
|
76
|
+
|
77
|
+
method_name = if ActiveSupport::Notifications.respond_to?(:monotonic_subscribe)
|
78
|
+
:monotonic_subscribe
|
79
|
+
else
|
80
|
+
:subscribe
|
81
|
+
end
|
82
|
+
|
83
|
+
subscriber = ActiveSupport::Notifications.public_send(method_name, "sql.active_record") do |_name, start, finish, _id, payload|
|
84
|
+
unless payload[:name] =~ /SCHEMA/
|
85
|
+
key = payload[:sql]
|
86
|
+
queries[key] ||= { count: 0, total_duration: 0, min_duration: nil, max_duration: nil }
|
87
|
+
queries[key][:count] += 1
|
88
|
+
duration = finish - start
|
89
|
+
queries[key][:total_duration] += duration
|
90
|
+
sql_duration += duration
|
91
|
+
|
92
|
+
if queries[key][:min_duration] == nil || queries[key][:min_duration] > duration
|
93
|
+
queries[key][:min_duration] = duration
|
94
|
+
end
|
95
|
+
|
96
|
+
if queries[key][:max_duration] == nil || queries[key][:max_duration] < duration
|
97
|
+
queries[key][:max_duration] = duration
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
total_duration = measure_duration do
|
103
|
+
block.call
|
104
|
+
end
|
105
|
+
|
106
|
+
queries = queries.reduce({}) do |agg, val|
|
107
|
+
val[1][:avg_duration] = val[1][:total_duration] / val[1][:count]
|
108
|
+
agg.merge(val[0] => val[1])
|
109
|
+
end
|
110
|
+
|
111
|
+
ActiveSupport::Notifications.unsubscribe(subscriber)
|
112
|
+
{
|
113
|
+
count: queries.reduce(0) { |agg, val| agg + val[1].fetch(:count) },
|
114
|
+
queries: queries,
|
115
|
+
total_duration: total_duration,
|
116
|
+
sql_duration: sql_duration
|
117
|
+
}
|
118
|
+
end
|
119
|
+
|
65
120
|
def self.index_info(args: {}, in_format: :display_table)
|
66
121
|
data = RailsPgExtras::IndexInfo.call(args[:table_name])
|
67
122
|
|
data/spec/smoke_spec.rb
CHANGED
@@ -29,6 +29,11 @@ describe RailsPgExtras do
|
|
29
29
|
end.not_to raise_error
|
30
30
|
end
|
31
31
|
|
32
|
+
it "collecting queries data works" do
|
33
|
+
output = RailsPgExtras.queries_data { RailsPgExtras.diagnose(in_format: :hash) }
|
34
|
+
expect(output.fetch(:count)).to eq 10
|
35
|
+
end
|
36
|
+
|
32
37
|
it "supports custom RAILS_PG_EXTRAS_DATABASE_URL" do
|
33
38
|
ENV['RAILS_PG_EXTRAS_DATABASE_URL'] = ENV['DATABASE_URL']
|
34
39
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rails-pg-extras
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 5.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- pawurb
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-
|
11
|
+
date: 2023-02-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: ruby-pg-extras
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - '='
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version:
|
19
|
+
version: 5.1.0
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - '='
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version:
|
26
|
+
version: 5.1.0
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: rails
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|