rails-pg-extras 0.5.2 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: cc8fd2765b1470aa6c7f8786b0f2cbe89ae543dfe02339091d5d4d3af8decb82
4
- data.tar.gz: c0d29ac67ae447bb91e75bd48a87a7d148cc6da05ab9430dd5b138be5d598a0f
3
+ metadata.gz: 20731f025eef43ea51d93e24a0af36bf8b1cf693343cd37ab6d44d6ae59b1939
4
+ data.tar.gz: f9d6b9b16ad4c67bc12129308923282d2d58cba133f586fbad91b8fb55769723
5
5
  SHA512:
6
- metadata.gz: 1a958d2044dd13b23daf446f7e776fc735800e5a7b7efcf90f52ec178c203c6442e920e3c97c41c82d34940835fa6de006e7de5be62838cad1842457adc60510
7
- data.tar.gz: b9f9d733cd3d292fe5282785458d46a40a051a76feb5504bd59f7d138844f091997635258c76cf08e561ffae47be80b3e68669db177a5be75c94f77583b53ac2
6
+ metadata.gz: 89b82f1052f8e1147efbfab860890324d2402356e9c2c84dbafaed5ef1945521d49a2e46f4fc080c7c50b812dd4d887e76ce01e8a07c8c86411af33b69685120
7
+ data.tar.gz: 504af4370b1e1a82f7ddd0bb048619e0d22d36928a332ade78e1e6c3509100cd155c331512917af123ca7c375805d658f97a507b1070ba8ac30249add48d21f2
data/.gitignore CHANGED
@@ -3,4 +3,5 @@ Gemfile.lock
3
3
  pkg/
4
4
  *.gem
5
5
  docker-compose.yml
6
+ .byebug_history
6
7
 
data/README.md CHANGED
@@ -366,7 +366,7 @@ This command outputs the Mandelbrot set, calculated through SQL.
366
366
 
367
367
  * Does is not violate the Heroku PG Extras license?
368
368
 
369
- The original plugin is [MIT based](https://github.com/heroku/heroku-pg-extras/blob/master/LICENSE) so it means that copying and redistribution in any format is permitted.
369
+ The original plugin is MIT based so it means that copying and redistribution in any format is permitted.
370
370
 
371
371
  ## Disclaimer
372
372
 
@@ -1,17 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'terminal-table'
4
+ require 'ruby-pg-extras'
4
5
 
5
6
  module RailsPGExtras
6
- QUERIES = %i(
7
- bloat blocking cache_hit
8
- calls extensions
9
- index_size index_usage locks all_locks
10
- long_running_queries mandelbrot outliers
11
- records_rank seq_scans table_indexes_size
12
- table_size total_index_size total_table_size
13
- unused_indexes vacuum_stats
14
- )
7
+ QUERIES = RubyPGExtras::QUERIES
15
8
 
16
9
  QUERIES.each do |query_name|
17
10
  define_singleton_method query_name do |options = { in_format: :display_table }|
@@ -24,71 +17,21 @@ module RailsPGExtras
24
17
 
25
18
  def self.run_query(query_name:, in_format:)
26
19
  result = connection.execute(
27
- sql_for(query_name: query_name)
20
+ RubyPGExtras.sql_for(query_name: query_name)
28
21
  )
29
22
 
30
- display_result(
23
+ RubyPGExtras.display_result(
31
24
  result,
32
- title: description_for(query_name: query_name),
25
+ title: RubyPGExtras.description_for(query_name: query_name),
33
26
  in_format: in_format
34
27
  )
35
28
  end
36
29
 
37
- def self.display_result(result, title:, in_format:)
38
- case in_format
39
- when :array
40
- result.values
41
- when :hash
42
- result.to_a
43
- when :raw
44
- result
45
- when :display_table
46
- headings = if result.count > 0
47
- result[0].keys
48
- else
49
- ["No results"]
50
- end
51
-
52
- puts Terminal::Table.new(
53
- title: title,
54
- headings: headings,
55
- rows: result.values
56
- )
57
- else
58
- raise "Invalid in_format option"
59
- end
60
- end
61
-
62
- def self.description_for(query_name:)
63
- first_line = File.open(
64
- sql_path_for(query_name: query_name)
65
- ) { |f| f.readline }
66
-
67
- first_line[/\/\*(.*?)\*\//m, 1].strip
68
- end
69
-
70
- def self.sql_for(query_name:)
71
- File.read(
72
- sql_path_for(query_name: query_name)
73
- )
74
- end
75
-
76
- def self.sql_path_for(query_name:)
77
- File.join(File.dirname(__FILE__), "/rails-pg-extras/queries/#{query_name}.sql")
78
- end
79
-
80
30
  def self.connection
81
31
  ActiveRecord::Base.connection
82
32
  end
83
33
 
84
- %i(
85
- connection
86
- display_result
87
- sql_for
88
- sql_path_for
89
- ).each do |method_name|
90
- private_class_method method_name
91
- end
34
+ private_class_method :connection
92
35
  end
93
36
 
94
37
  require 'rails-pg-extras/railtie' if defined?(Rails)
@@ -4,7 +4,7 @@ require 'rails-pg-extras'
4
4
 
5
5
  namespace :pg_extras do
6
6
  RailsPGExtras::QUERIES.each do |query_name|
7
- desc RailsPGExtras.description_for(query_name: query_name)
7
+ desc RubyPGExtras.description_for(query_name: query_name)
8
8
  task query_name.to_sym => :environment do
9
9
  RailsPGExtras.public_send(query_name)
10
10
  end
@@ -1,3 +1,3 @@
1
1
  module RailsPGExtras
2
- VERSION = "0.5.2"
2
+ VERSION = "0.6.0"
3
3
  end
@@ -18,6 +18,7 @@ Gem::Specification.new do |gem|
18
18
  gem.add_dependency "activerecord"
19
19
  gem.add_dependency "pg"
20
20
  gem.add_dependency "terminal-table"
21
+ gem.add_dependency "ruby-pg-extras", RailsPGExtras::VERSION
21
22
  gem.add_development_dependency "rake"
22
23
  gem.add_development_dependency "rspec"
23
24
  end
data/spec/smoke_spec.rb CHANGED
@@ -3,22 +3,12 @@
3
3
  require 'spec_helper'
4
4
 
5
5
  describe RailsPGExtras do
6
- RailsPGExtras::QUERIES.each do |query_name|
7
- it "#{query_name} description can be read" do
8
- expect do
9
- RailsPGExtras.description_for(
10
- query_name: query_name
11
- )
12
- end.not_to raise_error
13
- end
14
- end
15
-
16
6
  PG_STATS_DEPENDENT_QUERIES = %i(calls outliers)
17
7
 
18
8
  (RailsPGExtras::QUERIES - PG_STATS_DEPENDENT_QUERIES).each do |query_name|
19
9
  it "#{query_name} query can be executed" do
20
10
  expect do
21
- result = RailsPGExtras.run_query(
11
+ RailsPGExtras.run_query(
22
12
  query_name: query_name,
23
13
  in_format: :hash
24
14
  )
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: 0.5.2
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - pawurb
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-01-02 00:00:00.000000000 Z
11
+ date: 2020-01-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -52,6 +52,20 @@ dependencies:
52
52
  - - ">="
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: ruby-pg-extras
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - '='
60
+ - !ruby/object:Gem::Version
61
+ version: 0.6.0
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '='
67
+ - !ruby/object:Gem::Version
68
+ version: 0.6.0
55
69
  - !ruby/object:Gem::Dependency
56
70
  name: rake
57
71
  requirement: !ruby/object:Gem::Requirement
@@ -96,26 +110,6 @@ files:
96
110
  - README.md
97
111
  - Rakefile
98
112
  - lib/rails-pg-extras.rb
99
- - lib/rails-pg-extras/queries/all_locks.sql
100
- - lib/rails-pg-extras/queries/bloat.sql
101
- - lib/rails-pg-extras/queries/blocking.sql
102
- - lib/rails-pg-extras/queries/cache_hit.sql
103
- - lib/rails-pg-extras/queries/calls.sql
104
- - lib/rails-pg-extras/queries/extensions.sql
105
- - lib/rails-pg-extras/queries/index_size.sql
106
- - lib/rails-pg-extras/queries/index_usage.sql
107
- - lib/rails-pg-extras/queries/locks.sql
108
- - lib/rails-pg-extras/queries/long_running_queries.sql
109
- - lib/rails-pg-extras/queries/mandelbrot.sql
110
- - lib/rails-pg-extras/queries/outliers.sql
111
- - lib/rails-pg-extras/queries/records_rank.sql
112
- - lib/rails-pg-extras/queries/seq_scans.sql
113
- - lib/rails-pg-extras/queries/table_indexes_size.sql
114
- - lib/rails-pg-extras/queries/table_size.sql
115
- - lib/rails-pg-extras/queries/total_index_size.sql
116
- - lib/rails-pg-extras/queries/total_table_size.sql
117
- - lib/rails-pg-extras/queries/unused_indexes.sql
118
- - lib/rails-pg-extras/queries/vacuum_stats.sql
119
113
  - lib/rails-pg-extras/railtie.rb
120
114
  - lib/rails-pg-extras/tasks/all.rake
121
115
  - lib/rails-pg-extras/version.rb
@@ -1,16 +0,0 @@
1
- /* Queries with active locks */
2
-
3
- SELECT
4
- pg_stat_activity.pid,
5
- pg_class.relname,
6
- pg_locks.transactionid,
7
- pg_locks.granted,
8
- pg_locks.mode,
9
- pg_stat_activity.query AS query_snippet,
10
- age(now(),pg_stat_activity.query_start) AS "age"
11
- FROM pg_stat_activity,pg_locks left
12
- OUTER JOIN pg_class
13
- ON (pg_locks.relation = pg_class.oid)
14
- WHERE pg_stat_activity.query <> '<insufficient privilege>'
15
- AND pg_locks.pid = pg_stat_activity.pid
16
- AND pg_stat_activity.pid <> pg_backend_pid() order by query_start;
@@ -1,63 +0,0 @@
1
- /* Table and index bloat in your database ordered by most wasteful */
2
-
3
- WITH constants AS (
4
- SELECT current_setting('block_size')::numeric AS bs, 23 AS hdr, 4 AS ma
5
- ), bloat_info AS (
6
- SELECT
7
- ma,bs,schemaname,tablename,
8
- (datawidth+(hdr+ma-(case when hdr%ma=0 THEN ma ELSE hdr%ma END)))::numeric AS datahdr,
9
- (maxfracsum*(nullhdr+ma-(case when nullhdr%ma=0 THEN ma ELSE nullhdr%ma END))) AS nullhdr2
10
- FROM (
11
- SELECT
12
- schemaname, tablename, hdr, ma, bs,
13
- SUM((1-null_frac)*avg_width) AS datawidth,
14
- MAX(null_frac) AS maxfracsum,
15
- hdr+(
16
- SELECT 1+count(*)/8
17
- FROM pg_stats s2
18
- WHERE null_frac<>0 AND s2.schemaname = s.schemaname AND s2.tablename = s.tablename
19
- ) AS nullhdr
20
- FROM pg_stats s, constants
21
- GROUP BY 1,2,3,4,5
22
- ) AS foo
23
- ), table_bloat AS (
24
- SELECT
25
- schemaname, tablename, cc.relpages, bs,
26
- CEIL((cc.reltuples*((datahdr+ma-
27
- (CASE WHEN datahdr%ma=0 THEN ma ELSE datahdr%ma END))+nullhdr2+4))/(bs-20::float)) AS otta
28
- FROM bloat_info
29
- JOIN pg_class cc ON cc.relname = bloat_info.tablename
30
- JOIN pg_namespace nn ON cc.relnamespace = nn.oid AND nn.nspname = bloat_info.schemaname AND nn.nspname <> 'information_schema'
31
- ), index_bloat AS (
32
- SELECT
33
- schemaname, tablename, bs,
34
- COALESCE(c2.relname,'?') AS iname, COALESCE(c2.reltuples,0) AS ituples, COALESCE(c2.relpages,0) AS ipages,
35
- COALESCE(CEIL((c2.reltuples*(datahdr-12))/(bs-20::float)),0) AS iotta -- very rough approximation, assumes all cols
36
- FROM bloat_info
37
- JOIN pg_class cc ON cc.relname = bloat_info.tablename
38
- JOIN pg_namespace nn ON cc.relnamespace = nn.oid AND nn.nspname = bloat_info.schemaname AND nn.nspname <> 'information_schema'
39
- JOIN pg_index i ON indrelid = cc.oid
40
- JOIN pg_class c2 ON c2.oid = i.indexrelid
41
- )
42
- SELECT
43
- type, schemaname, object_name, bloat, pg_size_pretty(raw_waste) as waste
44
- FROM
45
- (SELECT
46
- 'table' as type,
47
- schemaname,
48
- tablename as object_name,
49
- ROUND(CASE WHEN otta=0 THEN 0.0 ELSE table_bloat.relpages/otta::numeric END,1) AS bloat,
50
- CASE WHEN relpages < otta THEN '0' ELSE (bs*(table_bloat.relpages-otta)::bigint)::bigint END AS raw_waste
51
- FROM
52
- table_bloat
53
- UNION
54
- SELECT
55
- 'index' as type,
56
- schemaname,
57
- tablename || '::' || iname as object_name,
58
- ROUND(CASE WHEN iotta=0 OR ipages=0 THEN 0.0 ELSE ipages/iotta::numeric END,1) AS bloat,
59
- CASE WHEN ipages < iotta THEN '0' ELSE (bs*(ipages-iotta))::bigint END AS raw_waste
60
- FROM
61
- index_bloat) bloat_summary
62
- ORDER BY raw_waste DESC, bloat DESC;
63
-
@@ -1,16 +0,0 @@
1
- /* Queries holding locks other queries are waiting to be released */
2
-
3
- SELECT bl.pid AS blocked_pid,
4
- ka.query AS blocking_statement,
5
- now() - ka.query_start AS blocking_duration,
6
- kl.pid AS blocking_pid,
7
- a.query AS blocked_statement,
8
- now() - a.query_start AS blocked_duration
9
- FROM pg_catalog.pg_locks bl
10
- JOIN pg_catalog.pg_stat_activity a
11
- ON bl.pid = a.pid
12
- JOIN pg_catalog.pg_locks kl
13
- JOIN pg_catalog.pg_stat_activity ka
14
- ON kl.pid = ka.pid
15
- ON bl.transactionid = kl.transactionid AND bl.pid != kl.pid
16
- WHERE NOT bl.granted;
@@ -1,11 +0,0 @@
1
- /* Index and table hit rate */
2
-
3
- SELECT
4
- 'index hit rate' AS name,
5
- (sum(idx_blks_hit)) / nullif(sum(idx_blks_hit + idx_blks_read),0) AS ratio
6
- FROM pg_statio_user_indexes
7
- UNION ALL
8
- SELECT
9
- 'table hit rate' AS name,
10
- sum(heap_blks_hit) / nullif(sum(heap_blks_hit) + sum(heap_blks_read),0) AS ratio
11
- FROM pg_statio_user_tables;
@@ -1,9 +0,0 @@
1
- /* 10 queries that have longest execution time in aggregate */
2
-
3
- SELECT query AS qry,
4
- interval '1 millisecond' * total_time AS exec_time,
5
- to_char((total_time/sum(total_time) OVER()) * 100, 'FM90D0') || '%' AS prop_exec_time,
6
- to_char(calls, 'FM999G999G990') AS ncalls,
7
- interval '1 millisecond' * (blk_read_time + blk_write_time) AS sync_io_time
8
- FROM pg_stat_statements WHERE userid = (SELECT usesysid FROM pg_user WHERE usename = current_user LIMIT 1)
9
- ORDER BY calls DESC LIMIT 10;
@@ -1,4 +0,0 @@
1
- /* Available and installed extensions */
2
-
3
- SELECT * FROM pg_available_extensions ORDER BY installed_version;
4
-
@@ -1,11 +0,0 @@
1
- /* The size of indexes, descending by size */
2
-
3
- SELECT c.relname AS name,
4
- pg_size_pretty(sum(c.relpages::bigint*8192)::bigint) AS size
5
- FROM pg_class c
6
- LEFT JOIN pg_namespace n ON (n.oid = c.relnamespace)
7
- WHERE n.nspname NOT IN ('pg_catalog', 'information_schema')
8
- AND n.nspname !~ '^pg_toast'
9
- AND c.relkind='i'
10
- GROUP BY c.relname
11
- ORDER BY sum(c.relpages) DESC;
@@ -1,12 +0,0 @@
1
- /* Index hit rate (effective databases are at 99% and up) */
2
-
3
- SELECT relname,
4
- CASE idx_scan
5
- WHEN 0 THEN 'Insufficient data'
6
- ELSE (100 * idx_scan / (seq_scan + idx_scan))::text
7
- END percent_of_times_index_used,
8
- n_live_tup rows_in_table
9
- FROM
10
- pg_stat_user_tables
11
- ORDER BY
12
- n_live_tup DESC;
@@ -1,16 +0,0 @@
1
- /* Queries with active exclusive locks */
2
-
3
- SELECT
4
- pg_stat_activity.pid,
5
- pg_class.relname,
6
- pg_locks.transactionid,
7
- pg_locks.granted,
8
- pg_stat_activity.query AS query_snippet,
9
- age(now(),pg_stat_activity.query_start) AS "age"
10
- FROM pg_stat_activity,pg_locks left
11
- OUTER JOIN pg_class
12
- ON (pg_locks.relation = pg_class.oid)
13
- WHERE pg_stat_activity.query <> '<insufficient privilege>'
14
- AND pg_locks.pid = pg_stat_activity.pid
15
- AND pg_locks.mode = 'ExclusiveLock'
16
- AND pg_stat_activity.pid <> pg_backend_pid() order by query_start;
@@ -1,14 +0,0 @@
1
- /* All queries longer than five minutes by descending duration */
2
-
3
- SELECT
4
- pid,
5
- now() - pg_stat_activity.query_start AS duration,
6
- query AS query
7
- FROM
8
- pg_stat_activity
9
- WHERE
10
- pg_stat_activity.query <> ''::text
11
- AND state <> 'idle'
12
- AND now() - pg_stat_activity.query_start > interval '5 minutes'
13
- ORDER BY
14
- now() - pg_stat_activity.query_start DESC;
@@ -1,21 +0,0 @@
1
- /* The mandelbrot set */
2
-
3
- WITH RECURSIVE Z(IX, IY, CX, CY, X, Y, I) AS (
4
- SELECT IX, IY, X::float, Y::float, X::float, Y::float, 0
5
- FROM (select -2.2 + 0.031 * i, i from generate_series(0,101) as i) as xgen(x,ix),
6
- (select -1.5 + 0.031 * i, i from generate_series(0,101) as i) as ygen(y,iy)
7
- UNION ALL
8
- SELECT IX, IY, CX, CY, X * X - Y * Y + CX AS X, Y * X * 2 + CY, I + 1
9
- FROM Z
10
- WHERE X * X + Y * Y < 16::float
11
- AND I < 100
12
- )
13
- SELECT array_to_string(array_agg(SUBSTRING(' .,,,-----++++%%%%@@@@#### ', LEAST(GREATEST(I,1),27), 1)),'')
14
- FROM (
15
- SELECT IX, IY, MAX(I) AS I
16
- FROM Z
17
- GROUP BY IY, IX
18
- ORDER BY IY, IX
19
- ) AS ZT
20
- GROUP BY IY
21
- ORDER BY IY;
@@ -1,10 +0,0 @@
1
- /* 10 queries that have longest execution time in aggregate */
2
-
3
- SELECT interval '1 millisecond' * total_time AS total_exec_time,
4
- to_char((total_time/sum(total_time) OVER()) * 100, 'FM90D0') || '%' AS prop_exec_time,
5
- to_char(calls, 'FM999G999G999G990') AS ncalls,
6
- interval '1 millisecond' * (blk_read_time + blk_write_time) AS sync_io_time,
7
- query AS query
8
- FROM pg_stat_statements WHERE userid = (SELECT usesysid FROM pg_user WHERE usename = current_user LIMIT 1)
9
- ORDER BY total_time DESC
10
- LIMIT 10;
@@ -1,9 +0,0 @@
1
- /* All tables and the number of rows in each ordered by number of rows descending */
2
-
3
- SELECT
4
- relname AS name,
5
- n_live_tup AS estimated_count
6
- FROM
7
- pg_stat_user_tables
8
- ORDER BY
9
- n_live_tup DESC;
@@ -1,7 +0,0 @@
1
- /* Count of sequential scans by table descending by order */
2
-
3
- SELECT relname AS name,
4
- seq_scan as count
5
- FROM
6
- pg_stat_user_tables
7
- ORDER BY seq_scan DESC;
@@ -1,10 +0,0 @@
1
- /* Total size of all the indexes on each table, descending by size */
2
-
3
- SELECT c.relname AS table,
4
- pg_size_pretty(pg_indexes_size(c.oid)) AS index_size
5
- FROM pg_class c
6
- LEFT JOIN pg_namespace n ON (n.oid = c.relnamespace)
7
- WHERE n.nspname NOT IN ('pg_catalog', 'information_schema')
8
- AND n.nspname !~ '^pg_toast'
9
- AND c.relkind='r'
10
- ORDER BY pg_indexes_size(c.oid) DESC;
@@ -1,10 +0,0 @@
1
- /* Size of the tables (excluding indexes), descending by size */
2
-
3
- SELECT c.relname AS name,
4
- pg_size_pretty(pg_table_size(c.oid)) AS size
5
- FROM pg_class c
6
- LEFT JOIN pg_namespace n ON (n.oid = c.relnamespace)
7
- WHERE n.nspname NOT IN ('pg_catalog', 'information_schema')
8
- AND n.nspname !~ '^pg_toast'
9
- AND c.relkind='r'
10
- ORDER BY pg_table_size(c.oid) DESC;
@@ -1,8 +0,0 @@
1
- /* Total size of all indexes in MB */
2
-
3
- SELECT pg_size_pretty(sum(c.relpages::bigint*8192)::bigint) AS size
4
- FROM pg_class c
5
- LEFT JOIN pg_namespace n ON (n.oid = c.relnamespace)
6
- WHERE n.nspname NOT IN ('pg_catalog', 'information_schema')
7
- AND n.nspname !~ '^pg_toast'
8
- AND c.relkind='i';
@@ -1,10 +0,0 @@
1
- /* Size of the tables (including indexes), descending by size */
2
-
3
- SELECT c.relname AS name,
4
- pg_size_pretty(pg_total_relation_size(c.oid)) AS size
5
- FROM pg_class c
6
- LEFT JOIN pg_namespace n ON (n.oid = c.relnamespace)
7
- WHERE n.nspname NOT IN ('pg_catalog', 'information_schema')
8
- AND n.nspname !~ '^pg_toast'
9
- AND c.relkind='r'
10
- ORDER BY pg_total_relation_size(c.oid) DESC;
@@ -1,16 +0,0 @@
1
- /* Unused and almost unused indexes */
2
- /* Ordered by their size relative to the number of index scans.
3
- Exclude indexes of very small tables (less than 5 pages),
4
- where the planner will almost invariably select a sequential scan,
5
- but may not in the future as the table grows */
6
-
7
- SELECT
8
- schemaname || '.' || relname AS table,
9
- indexrelname AS index,
10
- pg_size_pretty(pg_relation_size(i.indexrelid)) AS index_size,
11
- idx_scan as index_scans
12
- FROM pg_stat_user_indexes ui
13
- JOIN pg_index i ON ui.indexrelid = i.indexrelid
14
- WHERE NOT indisunique AND idx_scan < 50 AND pg_relation_size(relid) > 5 * 8192
15
- ORDER BY pg_relation_size(i.indexrelid) / nullif(idx_scan, 0) DESC NULLS FIRST,
16
- pg_relation_size(i.indexrelid) DESC;
@@ -1,40 +0,0 @@
1
- /* Dead rows and whether an automatic vacuum is expected to be triggered */
2
-
3
- WITH table_opts AS (
4
- SELECT
5
- pg_class.oid, relname, nspname, array_to_string(reloptions, '') AS relopts
6
- FROM
7
- pg_class INNER JOIN pg_namespace ns ON relnamespace = ns.oid
8
- ), vacuum_settings AS (
9
- SELECT
10
- oid, relname, nspname,
11
- CASE
12
- WHEN relopts LIKE '%autovacuum_vacuum_threshold%'
13
- THEN substring(relopts, '.*autovacuum_vacuum_threshold=([0-9.]+).*')::integer
14
- ELSE current_setting('autovacuum_vacuum_threshold')::integer
15
- END AS autovacuum_vacuum_threshold,
16
- CASE
17
- WHEN relopts LIKE '%autovacuum_vacuum_scale_factor%'
18
- THEN substring(relopts, '.*autovacuum_vacuum_scale_factor=([0-9.]+).*')::real
19
- ELSE current_setting('autovacuum_vacuum_scale_factor')::real
20
- END AS autovacuum_vacuum_scale_factor
21
- FROM
22
- table_opts
23
- )
24
- SELECT
25
- vacuum_settings.nspname AS schema,
26
- vacuum_settings.relname AS table,
27
- to_char(psut.last_vacuum, 'YYYY-MM-DD HH24:MI') AS last_vacuum,
28
- to_char(psut.last_autovacuum, 'YYYY-MM-DD HH24:MI') AS last_autovacuum,
29
- to_char(pg_class.reltuples, '9G999G999G999') AS rowcount,
30
- to_char(psut.n_dead_tup, '9G999G999G999') AS dead_rowcount,
31
- to_char(autovacuum_vacuum_threshold
32
- + (autovacuum_vacuum_scale_factor::numeric * pg_class.reltuples), '9G999G999G999') AS autovacuum_threshold,
33
- CASE
34
- WHEN autovacuum_vacuum_threshold + (autovacuum_vacuum_scale_factor::numeric * pg_class.reltuples) < psut.n_dead_tup
35
- THEN 'yes'
36
- END AS expect_autovacuum
37
- FROM
38
- pg_stat_user_tables psut INNER JOIN pg_class ON psut.relid = pg_class.oid
39
- INNER JOIN vacuum_settings ON pg_class.oid = vacuum_settings.oid
40
- ORDER BY 1;