gitlab-exporter 7.1.2 → 10.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitlab-ci.yml +1 -1
- data/.rubocop.yml +7 -5
- data/.rubocop_todo.yml +64 -0
- data/.ruby-version +1 -0
- data/Gemfile.lock +26 -15
- data/bin/gitlab-exporter +3 -1
- data/config/gitlab-exporter.yml.example +10 -0
- data/gitlab-exporter.gemspec +5 -4
- data/lib/gitlab_exporter.rb +1 -0
- data/lib/gitlab_exporter/cli.rb +1 -2
- data/lib/gitlab_exporter/database/base.rb +33 -10
- data/lib/gitlab_exporter/database/bloat.rb +2 -2
- data/lib/gitlab_exporter/database/bloat_btree.sql +84 -67
- data/lib/gitlab_exporter/database/bloat_table.sql +13 -12
- data/lib/gitlab_exporter/database/ci_builds.rb +4 -3
- data/lib/gitlab_exporter/database/row_count.rb +7 -25
- data/lib/gitlab_exporter/database/tuple_stats.rb +4 -2
- data/lib/gitlab_exporter/git.rb +8 -1
- data/lib/gitlab_exporter/memstats.rb +1 -1
- data/lib/gitlab_exporter/memstats/mapping.rb +1 -1
- data/lib/gitlab_exporter/process.rb +13 -3
- data/lib/gitlab_exporter/ruby.rb +21 -0
- data/lib/gitlab_exporter/sidekiq.rb +83 -69
- data/lib/gitlab_exporter/util.rb +1 -1
- data/lib/gitlab_exporter/version.rb +1 -1
- data/lib/gitlab_exporter/web_exporter.rb +23 -1
- data/spec/database/bloat_spec.rb +1 -1
- data/spec/database/ci_builds_spec.rb +23 -23
- data/spec/git_process_proper_spec.rb +1 -1
- data/spec/memstats_spec.rb +3 -3
- data/spec/ruby_spec.rb +25 -0
- data/spec/spec_helper.rb +2 -4
- metadata +36 -17
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0f7115d7a7e8604d15ad7734afd3280c22edf9f6911af159f9386f2a9d495701
|
4
|
+
data.tar.gz: 7b050b23851b8073da229a5347b0c22afd641a1420859f37f0a0b8a7a4113244
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 848007d860313f8d62239b3f97a9024944aec9ddbfe6ea97472eaae64ddfc6e03cc056fe9466ce719209a6fad2b5a88947ff085f25ed6cf4ecf6421c1db576d7
|
7
|
+
data.tar.gz: f751e8af1eea6d30eb00dae65ec41681b50e9481a392b6521fde15c07934d8550dd2c3e3b65ea13ae6cbc0adadfe30986bad418c88172699b3172d20f9f62a75
|
data/.gitlab-ci.yml
CHANGED
@@ -7,7 +7,7 @@ include:
|
|
7
7
|
- template: Security/Secret-Detection.gitlab-ci.yml # https://gitlab.com/gitlab-org/gitlab-foss/-/blob/master/lib/gitlab/ci/templates/Security/Secret-Detection.gitlab-ci.yml
|
8
8
|
|
9
9
|
default:
|
10
|
-
image:
|
10
|
+
image: ruby:2.7
|
11
11
|
cache:
|
12
12
|
paths:
|
13
13
|
- vendor
|
data/.rubocop.yml
CHANGED
@@ -1,5 +1,7 @@
|
|
1
|
+
inherit_from: .rubocop_todo.yml
|
2
|
+
|
1
3
|
AllCops:
|
2
|
-
TargetRubyVersion: 2.
|
4
|
+
TargetRubyVersion: 2.7
|
3
5
|
DisplayCopNames: true
|
4
6
|
|
5
7
|
# Just use double quotes please
|
@@ -20,15 +22,15 @@ Style/RaiseArgs:
|
|
20
22
|
Style/FrozenStringLiteralComment:
|
21
23
|
Enabled: false
|
22
24
|
|
25
|
+
# Commonly used screens these days easily fit more than 80 characters.
|
26
|
+
Layout/LineLength:
|
27
|
+
Max: 120
|
28
|
+
|
23
29
|
Metrics/MethodLength:
|
24
30
|
Max: 15
|
25
31
|
|
26
32
|
Metrics/AbcSize:
|
27
33
|
Enabled: false
|
28
34
|
|
29
|
-
# Commonly used screens these days easily fit more than 80 characters.
|
30
|
-
Metrics/LineLength:
|
31
|
-
Max: 120
|
32
|
-
|
33
35
|
Metrics/ClassLength:
|
34
36
|
Max: 150
|
data/.rubocop_todo.yml
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
# This configuration was generated by
|
2
|
+
# `rubocop --auto-gen-config`
|
3
|
+
# on 2021-01-11 12:24:03 UTC using RuboCop version 0.93.1.
|
4
|
+
# The point is for the user to remove these configuration records
|
5
|
+
# one by one as the offenses are removed from the code base.
|
6
|
+
# Note that changes in the inspected code, or installation of new
|
7
|
+
# versions of RuboCop, may require this file to be generated again.
|
8
|
+
|
9
|
+
# Offense count: 1
|
10
|
+
# Configuration parameters: Include.
|
11
|
+
# Include: **/*.gemspec
|
12
|
+
Gemspec/RequiredRubyVersion:
|
13
|
+
Exclude:
|
14
|
+
- 'gitlab-exporter.gemspec'
|
15
|
+
|
16
|
+
# Offense count: 3
|
17
|
+
Lint/AmbiguousBlockAssociation:
|
18
|
+
Exclude:
|
19
|
+
- 'spec/git_spec.rb'
|
20
|
+
- 'spec/util_spec.rb'
|
21
|
+
|
22
|
+
# Offense count: 2
|
23
|
+
# Configuration parameters: MaximumRangeSize.
|
24
|
+
Lint/MissingCopEnableDirective:
|
25
|
+
Exclude:
|
26
|
+
- 'spec/database/ci_builds_spec.rb'
|
27
|
+
- 'spec/git_process_proper_spec.rb'
|
28
|
+
|
29
|
+
# Offense count: 1
|
30
|
+
# Cop supports --auto-correct.
|
31
|
+
Lint/NonDeterministicRequireOrder:
|
32
|
+
Exclude:
|
33
|
+
- 'spec/spec_helper.rb'
|
34
|
+
|
35
|
+
# Offense count: 16
|
36
|
+
# Configuration parameters: CountComments, CountAsOne, ExcludedMethods.
|
37
|
+
# ExcludedMethods: refine
|
38
|
+
Metrics/BlockLength:
|
39
|
+
Max: 349
|
40
|
+
|
41
|
+
# Offense count: 1
|
42
|
+
# Configuration parameters: IgnoredMethods.
|
43
|
+
Metrics/CyclomaticComplexity:
|
44
|
+
Max: 8
|
45
|
+
|
46
|
+
# Offense count: 1
|
47
|
+
# Configuration parameters: IgnoredMethods.
|
48
|
+
Metrics/PerceivedComplexity:
|
49
|
+
Max: 9
|
50
|
+
|
51
|
+
# Offense count: 1
|
52
|
+
# Configuration parameters: EnforcedStyle, AllowModifiersOnSymbols.
|
53
|
+
# SupportedStyles: inline, group
|
54
|
+
Style/AccessModifierDeclarations:
|
55
|
+
Exclude:
|
56
|
+
- 'lib/gitlab_exporter/util.rb'
|
57
|
+
|
58
|
+
# Offense count: 2
|
59
|
+
# Cop supports --auto-correct.
|
60
|
+
# Configuration parameters: ConvertCodeThatCanStartToReturnNil, AllowedMethods.
|
61
|
+
# AllowedMethods: present?, blank?, presence, try, try!
|
62
|
+
Style/SafeNavigation:
|
63
|
+
Exclude:
|
64
|
+
- 'lib/gitlab_exporter/database/base.rb'
|
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
2.7.2
|
data/Gemfile.lock
CHANGED
@@ -1,9 +1,10 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
gitlab-exporter (
|
4
|
+
gitlab-exporter (10.0.0)
|
5
5
|
connection_pool (~> 2.2.1)
|
6
6
|
pg (~> 1.1)
|
7
|
+
puma (~> 5.1.1)
|
7
8
|
quantile (~> 0.2.0)
|
8
9
|
redis (~> 4.1.2)
|
9
10
|
redis-namespace (~> 1.6.0)
|
@@ -13,23 +14,28 @@ PATH
|
|
13
14
|
GEM
|
14
15
|
remote: https://rubygems.org/
|
15
16
|
specs:
|
16
|
-
ast (2.4.
|
17
|
+
ast (2.4.1)
|
17
18
|
connection_pool (2.2.3)
|
18
19
|
diff-lcs (1.3)
|
19
20
|
mustermann (1.1.1)
|
20
21
|
ruby2_keywords (~> 0.0.1)
|
21
|
-
|
22
|
-
|
22
|
+
nio4r (2.5.4)
|
23
|
+
parallel (1.20.1)
|
24
|
+
parser (3.0.0.0)
|
25
|
+
ast (~> 2.4.1)
|
23
26
|
pg (1.2.3)
|
24
|
-
|
27
|
+
puma (5.1.1)
|
28
|
+
nio4r (~> 2.0)
|
25
29
|
quantile (0.2.1)
|
26
30
|
rack (2.2.3)
|
27
31
|
rack-protection (2.0.8.1)
|
28
32
|
rack
|
29
|
-
rainbow (
|
33
|
+
rainbow (3.0.0)
|
30
34
|
redis (4.1.4)
|
31
35
|
redis-namespace (1.6.0)
|
32
36
|
redis (>= 3.0.4)
|
37
|
+
regexp_parser (2.0.3)
|
38
|
+
rexml (3.2.4)
|
33
39
|
rspec (3.7.0)
|
34
40
|
rspec-core (~> 3.7.0)
|
35
41
|
rspec-expectations (~> 3.7.0)
|
@@ -43,14 +49,19 @@ GEM
|
|
43
49
|
diff-lcs (>= 1.2.0, < 2.0)
|
44
50
|
rspec-support (~> 3.7.0)
|
45
51
|
rspec-support (3.7.1)
|
46
|
-
rubocop (0.
|
47
|
-
|
48
|
-
|
49
|
-
rainbow (>=
|
52
|
+
rubocop (0.93.1)
|
53
|
+
parallel (~> 1.10)
|
54
|
+
parser (>= 2.7.1.5)
|
55
|
+
rainbow (>= 2.2.2, < 4.0)
|
56
|
+
regexp_parser (>= 1.8)
|
57
|
+
rexml
|
58
|
+
rubocop-ast (>= 0.6.0)
|
50
59
|
ruby-progressbar (~> 1.7)
|
51
|
-
unicode-display_width (
|
52
|
-
|
53
|
-
|
60
|
+
unicode-display_width (>= 1.4.0, < 2.0)
|
61
|
+
rubocop-ast (1.4.0)
|
62
|
+
parser (>= 2.7.1.5)
|
63
|
+
ruby-progressbar (1.11.0)
|
64
|
+
ruby2_keywords (0.0.4)
|
54
65
|
sidekiq (5.2.9)
|
55
66
|
connection_pool (~> 2.2, >= 2.2.2)
|
56
67
|
rack (~> 2.0)
|
@@ -62,7 +73,7 @@ GEM
|
|
62
73
|
rack-protection (= 2.0.8.1)
|
63
74
|
tilt (~> 2.0)
|
64
75
|
tilt (2.0.10)
|
65
|
-
unicode-display_width (1.
|
76
|
+
unicode-display_width (1.7.0)
|
66
77
|
|
67
78
|
PLATFORMS
|
68
79
|
ruby
|
@@ -74,4 +85,4 @@ DEPENDENCIES
|
|
74
85
|
rubocop (~> 0.42)
|
75
86
|
|
76
87
|
BUNDLED WITH
|
77
|
-
1.
|
88
|
+
2.1.4
|
data/bin/gitlab-exporter
CHANGED
@@ -6,6 +6,7 @@ db_common: &db_common
|
|
6
6
|
|
7
7
|
# Web server config
|
8
8
|
server:
|
9
|
+
name: puma # cf. https://github.com/sinatra/sinatra#available-settings
|
9
10
|
listen_address: 0.0.0.0
|
10
11
|
listen_port: 9168
|
11
12
|
# Maximum amount of memory to use in megabytes, after which the process is killed
|
@@ -94,12 +95,21 @@ probes:
|
|
94
95
|
redis_url: "redis://localhost:6379"
|
95
96
|
redis_enable_client: true
|
96
97
|
|
98
|
+
ruby: &ruby
|
99
|
+
class_name: RubyProber
|
100
|
+
methods:
|
101
|
+
- probe_gc
|
102
|
+
opts:
|
103
|
+
quantiles: false
|
104
|
+
|
97
105
|
metrics:
|
98
106
|
multiple: true
|
99
107
|
git_process:
|
100
108
|
<<: *git_process
|
101
109
|
process:
|
102
110
|
<<: *process
|
111
|
+
ruby:
|
112
|
+
<<: *ruby
|
103
113
|
sidekiq:
|
104
114
|
<<: *sidekiq
|
105
115
|
ci_builds:
|
data/gitlab-exporter.gemspec
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
lib = File.expand_path("
|
1
|
+
lib = File.expand_path("lib", __dir__)
|
2
2
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
3
3
|
require "gitlab_exporter/version"
|
4
4
|
|
@@ -20,13 +20,14 @@ Gem::Specification.new do |s|
|
|
20
20
|
s.homepage = "http://gitlab.com"
|
21
21
|
s.license = "MIT"
|
22
22
|
|
23
|
+
s.add_runtime_dependency "connection_pool", "~> 2.2.1"
|
23
24
|
s.add_runtime_dependency "pg", "~> 1.1"
|
24
|
-
s.add_runtime_dependency "
|
25
|
+
s.add_runtime_dependency "puma", "~> 5.1.1"
|
25
26
|
s.add_runtime_dependency "quantile", "~> 0.2.0"
|
26
|
-
s.add_runtime_dependency "sidekiq", "~> 5.2.1"
|
27
27
|
s.add_runtime_dependency "redis", "~> 4.1.2"
|
28
28
|
s.add_runtime_dependency "redis-namespace", "~> 1.6.0"
|
29
|
-
s.add_runtime_dependency "
|
29
|
+
s.add_runtime_dependency "sidekiq", "~> 5.2.1"
|
30
|
+
s.add_runtime_dependency "sinatra", "~> 2.0.4"
|
30
31
|
|
31
32
|
s.add_development_dependency "rspec", "~> 3.7.0"
|
32
33
|
s.add_development_dependency "rspec-expectations", "~> 3.7.0"
|
data/lib/gitlab_exporter.rb
CHANGED
data/lib/gitlab_exporter/cli.rb
CHANGED
@@ -19,8 +19,7 @@ module GitLab
|
|
19
19
|
# Empty runner that will raise an InvalidCLICommand when executed to provide the usage
|
20
20
|
# in the exception message
|
21
21
|
class NullRunner
|
22
|
-
def initialize(args)
|
23
|
-
end
|
22
|
+
def initialize(args); end
|
24
23
|
|
25
24
|
def run
|
26
25
|
fail InvalidCLICommand.new("Usage: #{EXECUTABLE_NAME} <command> [options] [arguments...]\n\n"\
|
@@ -8,14 +8,39 @@ module GitLab
|
|
8
8
|
#
|
9
9
|
# It takes a connection string (e.g. "dbname=test port=5432")
|
10
10
|
class Base
|
11
|
+
POOL_SIZE = 3
|
12
|
+
|
13
|
+
# This timeout is configured to higher interval than scrapping
|
14
|
+
# of Prometheus to ensure that connection is kept instead of
|
15
|
+
# needed to be re-initialized
|
16
|
+
POOL_TIMEOUT = 90
|
17
|
+
|
11
18
|
def self.connection_pool
|
12
|
-
|
13
|
-
h[connection_string] = ConnectionPool.new(size:
|
14
|
-
PG.connect(connection_string)
|
19
|
+
@@connection_pool ||= Hash.new do |h, connection_string| # rubocop:disable Style/ClassVars
|
20
|
+
h[connection_string] = ConnectionPool.new(size: POOL_SIZE, timeout: POOL_TIMEOUT) do
|
21
|
+
PG.connect(connection_string).tap do |conn|
|
22
|
+
configure_type_map_for_results(conn)
|
23
|
+
end
|
15
24
|
end
|
16
25
|
end
|
17
26
|
end
|
18
27
|
|
28
|
+
def self.configure_type_map_for_results(conn)
|
29
|
+
tm = PG::BasicTypeMapForResults.new(conn)
|
30
|
+
|
31
|
+
# Remove warning message:
|
32
|
+
# Warning: no type cast defined for type "name" with oid 19.
|
33
|
+
# Please cast this type explicitly to TEXT to be safe for future changes.
|
34
|
+
# Warning: no type cast defined for type "regproc" with oid 24.
|
35
|
+
# Please cast this type explicitly to TEXT to be safe for future changes.
|
36
|
+
[{ "type": "text", "oid": 19 }, { "type": "int4", "oid": 24 }].each do |value|
|
37
|
+
old_coder = tm.coders.find { |c| c.name == value[:type] }
|
38
|
+
tm.add_coder(old_coder.dup.tap { |c| c.oid = value[:oid] })
|
39
|
+
end
|
40
|
+
|
41
|
+
conn.type_map_for_results = tm
|
42
|
+
end
|
43
|
+
|
19
44
|
def initialize(args, logger: nil)
|
20
45
|
@connection_string = args[:connection_string]
|
21
46
|
@logger = logger
|
@@ -31,13 +56,11 @@ module GitLab
|
|
31
56
|
|
32
57
|
def with_connection_pool
|
33
58
|
connection_pool.with do |conn|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
raise e
|
40
|
-
end
|
59
|
+
yield conn
|
60
|
+
rescue PG::UnableToSend => e
|
61
|
+
@logger.warn "Error sending to the database: #{e}" if @logger
|
62
|
+
conn.reset
|
63
|
+
raise e
|
41
64
|
end
|
42
65
|
rescue PG::Error => e
|
43
66
|
@logger.error "Error connecting to the database: #{e}" if @logger
|
@@ -35,7 +35,7 @@ module GitLab
|
|
35
35
|
|
36
36
|
# Prober class to gather bloat metrics
|
37
37
|
class BloatProber
|
38
|
-
METRIC_KEYS = %w
|
38
|
+
METRIC_KEYS = %w[bloat_ratio bloat_size extra_size real_size].freeze
|
39
39
|
|
40
40
|
attr_reader :metrics, :collector, :bloat_types
|
41
41
|
|
@@ -46,7 +46,7 @@ module GitLab
|
|
46
46
|
@metrics = metrics
|
47
47
|
@collector = collector
|
48
48
|
@collector.logger = logger
|
49
|
-
@bloat_types = opts[:bloat_types] || %i
|
49
|
+
@bloat_types = opts[:bloat_types] || %i[btree table]
|
50
50
|
end
|
51
51
|
|
52
52
|
def probe_db
|
@@ -12,73 +12,90 @@ SELECT current_database(), nspname AS schemaname, tblname, idxname AS object_nam
|
|
12
12
|
END AS bloat_size,
|
13
13
|
100 * (relpages-est_pages_ff)::float / relpages AS bloat_ratio,
|
14
14
|
is_na
|
15
|
-
-- , 100-(
|
15
|
+
-- , 100-(pst).avg_leaf_density AS pst_avg_bloat, est_pages, index_tuple_hdr_bm, maxalign, pagehdr, nulldatawidth, nulldatahdrwidth, reltuples, relpages -- (DEBUG INFO)
|
16
16
|
FROM (
|
17
17
|
SELECT coalesce(1 +
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
18
|
+
ceil(reltuples/floor((bs-pageopqdata-pagehdr)/(4+nulldatahdrwidth)::float)), 0 -- ItemIdData size + computed avg size of a tuple (nulldatahdrwidth)
|
19
|
+
) AS est_pages,
|
20
|
+
coalesce(1 +
|
21
|
+
ceil(reltuples/floor((bs-pageopqdata-pagehdr)*fillfactor/(100*(4+nulldatahdrwidth)::float))), 0
|
22
|
+
) AS est_pages_ff,
|
23
|
+
bs, nspname, tblname, idxname, relpages, fillfactor, is_na
|
24
|
+
-- , pgstatindex(idxoid) AS pst, index_tuple_hdr_bm, maxalign, pagehdr, nulldatawidth, nulldatahdrwidth, reltuples -- (DEBUG INFO)
|
25
25
|
FROM (
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
) AS
|
82
|
-
|
83
|
-
|
84
|
-
|
26
|
+
SELECT maxalign, bs, nspname, tblname, idxname, reltuples, relpages, idxoid, fillfactor,
|
27
|
+
( index_tuple_hdr_bm +
|
28
|
+
maxalign - CASE -- Add padding to the index tuple header to align on MAXALIGN
|
29
|
+
WHEN index_tuple_hdr_bm%maxalign = 0 THEN maxalign
|
30
|
+
ELSE index_tuple_hdr_bm%maxalign
|
31
|
+
END
|
32
|
+
+ nulldatawidth + maxalign - CASE -- Add padding to the data to align on MAXALIGN
|
33
|
+
WHEN nulldatawidth = 0 THEN 0
|
34
|
+
WHEN nulldatawidth::integer%maxalign = 0 THEN maxalign
|
35
|
+
ELSE nulldatawidth::integer%maxalign
|
36
|
+
END
|
37
|
+
)::numeric AS nulldatahdrwidth, pagehdr, pageopqdata, is_na
|
38
|
+
-- , index_tuple_hdr_bm, nulldatawidth -- (DEBUG INFO)
|
39
|
+
FROM (
|
40
|
+
SELECT n.nspname, i.tblname, i.idxname, i.reltuples, i.relpages,
|
41
|
+
i.idxoid, i.fillfactor, current_setting('block_size')::numeric AS bs,
|
42
|
+
CASE -- MAXALIGN: 4 on 32bits, 8 on 64bits (and mingw32 ?)
|
43
|
+
WHEN version() ~ 'mingw32' OR version() ~ '64-bit|x86_64|ppc64|ia64|amd64' THEN 8
|
44
|
+
ELSE 4
|
45
|
+
END AS maxalign,
|
46
|
+
/* per page header, fixed size: 20 for 7.X, 24 for others */
|
47
|
+
24 AS pagehdr,
|
48
|
+
/* per page btree opaque data */
|
49
|
+
16 AS pageopqdata,
|
50
|
+
/* per tuple header: add IndexAttributeBitMapData if some cols are null-able */
|
51
|
+
CASE WHEN max(coalesce(s.null_frac,0)) = 0
|
52
|
+
THEN 2 -- IndexTupleData size
|
53
|
+
ELSE 2 + (( 32 + 8 - 1 ) / 8) -- IndexTupleData size + IndexAttributeBitMapData size ( max num filed per index + 8 - 1 /8)
|
54
|
+
END AS index_tuple_hdr_bm,
|
55
|
+
/* data len: we remove null values save space using it fractionnal part from stats */
|
56
|
+
sum( (1-coalesce(s.null_frac, 0)) * coalesce(s.avg_width, 1024)) AS nulldatawidth,
|
57
|
+
max( CASE WHEN i.atttypid = 'pg_catalog.name'::regtype THEN 1 ELSE 0 END ) > 0 AS is_na
|
58
|
+
FROM (
|
59
|
+
SELECT ct.relname AS tblname, ct.relnamespace, ic.idxname, ic.attpos, ic.indkey, ic.indkey[ic.attpos], ic.reltuples, ic.relpages, ic.tbloid, ic.idxoid, ic.fillfactor,
|
60
|
+
coalesce(a1.attnum, a2.attnum) AS attnum, coalesce(a1.attname, a2.attname) AS attname, coalesce(a1.atttypid, a2.atttypid) AS atttypid,
|
61
|
+
CASE WHEN a1.attnum IS NULL
|
62
|
+
THEN ic.idxname
|
63
|
+
ELSE ct.relname
|
64
|
+
END AS attrelname
|
65
|
+
FROM (
|
66
|
+
SELECT idxname, reltuples, relpages, tbloid, idxoid, fillfactor, indkey,
|
67
|
+
pg_catalog.generate_series(1,indnatts) AS attpos
|
68
|
+
FROM (
|
69
|
+
SELECT ci.relname AS idxname, ci.reltuples, ci.relpages, i.indrelid AS tbloid,
|
70
|
+
i.indexrelid AS idxoid,
|
71
|
+
coalesce(substring(
|
72
|
+
array_to_string(ci.reloptions, ' ')
|
73
|
+
from 'fillfactor=([0-9]+)')::smallint, 90) AS fillfactor,
|
74
|
+
i.indnatts,
|
75
|
+
pg_catalog.string_to_array(pg_catalog.textin(
|
76
|
+
pg_catalog.int2vectorout(i.indkey)),' ')::int[] AS indkey
|
77
|
+
FROM pg_catalog.pg_index i
|
78
|
+
JOIN pg_catalog.pg_class ci ON ci.oid = i.indexrelid
|
79
|
+
WHERE ci.relam=(SELECT oid FROM pg_am WHERE amname = 'btree')
|
80
|
+
AND ci.relpages > 0
|
81
|
+
) AS idx_data
|
82
|
+
) AS ic
|
83
|
+
JOIN pg_catalog.pg_class ct ON ct.oid = ic.tbloid
|
84
|
+
LEFT JOIN pg_catalog.pg_attribute a1 ON
|
85
|
+
ic.indkey[ic.attpos] <> 0
|
86
|
+
AND a1.attrelid = ic.tbloid
|
87
|
+
AND a1.attnum = ic.indkey[ic.attpos]
|
88
|
+
LEFT JOIN pg_catalog.pg_attribute a2 ON
|
89
|
+
ic.indkey[ic.attpos] = 0
|
90
|
+
AND a2.attrelid = ic.idxoid
|
91
|
+
AND a2.attnum = ic.attpos
|
92
|
+
) i
|
93
|
+
JOIN pg_catalog.pg_namespace n ON n.oid = i.relnamespace
|
94
|
+
JOIN pg_catalog.pg_stats s ON s.schemaname = n.nspname
|
95
|
+
AND s.tablename = i.attrelname
|
96
|
+
AND s.attname = i.attname
|
97
|
+
GROUP BY 1,2,3,4,5,6,7,8,9,10,11
|
98
|
+
) AS rows_data_stats
|
99
|
+
) AS rows_hdr_pdg_stats
|
100
|
+
) AS relation_stats
|
101
|
+
ORDER BY nspname, tblname, idxname;
|