pgdexter 0.5.2 → 0.5.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +10 -0
- data/lib/dexter/indexer.rb +21 -10
- data/lib/dexter/query.rb +1 -1
- data/lib/dexter/version.rb +1 -1
- metadata +16 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 037ac99e7dff1ac6edb6fddf8e85ae8357c6af25bc83dde1e5281f87c247ec4c
|
4
|
+
data.tar.gz: 1256486b21d6d6f91186a1a4e3ca0c1c39c7e318b26335d5cd86f82252b7ec42
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4bc5d0355a53b867da9710a23edc7a898bd23f112ee93beee246b04584175609ac750f9819cb1be041b26f36db407363601e57a5cb8effb49214148c9ef688cb
|
7
|
+
data.tar.gz: a9019542cfefe04789426309834f7688cc59b8dea8d2d4f3d4559b349ae5bb72bf56de4bcd7ee54ec2483f41df85edec8dfd62f4e2e4db79d30117a874a02fd8
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,13 @@
|
|
1
|
+
## 0.5.4 (2024-04-03)
|
2
|
+
|
3
|
+
- Fixed issue with processing over 500 query fingerprints (introduced in 0.5.3)
|
4
|
+
- Require google-protobuf < 4
|
5
|
+
|
6
|
+
## 0.5.3 (2024-03-05)
|
7
|
+
|
8
|
+
- Fixed error with hypothetical index limit
|
9
|
+
- Fixed error with foreign tables
|
10
|
+
|
1
11
|
## 0.5.2 (2024-01-10)
|
2
12
|
|
3
13
|
- Added Docker image for `linux/arm64`
|
data/lib/dexter/indexer.rb
CHANGED
@@ -96,10 +96,16 @@ module Dexter
|
|
96
96
|
analyze_tables(tables) if tables.any? && (@analyze || @log_level == "debug2")
|
97
97
|
|
98
98
|
# create hypothetical indexes and explain queries
|
99
|
-
|
99
|
+
if tables.any?
|
100
|
+
# process in batches to prevent "hypopg: not more oid available" error
|
101
|
+
# https://hypopg.readthedocs.io/en/rel1_stable/usage.html#configuration
|
102
|
+
queries.select(&:candidate_tables).each_slice(500) do |batch|
|
103
|
+
create_hypothetical_indexes(batch)
|
104
|
+
end
|
105
|
+
end
|
100
106
|
|
101
107
|
# see if new indexes were used and meet bar
|
102
|
-
new_indexes = determine_indexes(queries,
|
108
|
+
new_indexes = determine_indexes(queries, tables)
|
103
109
|
|
104
110
|
# display and create new indexes
|
105
111
|
show_and_create_indexes(new_indexes, queries)
|
@@ -183,6 +189,8 @@ module Dexter
|
|
183
189
|
def create_hypothetical_indexes(queries)
|
184
190
|
candidates = {}
|
185
191
|
|
192
|
+
reset_hypothetical_indexes
|
193
|
+
|
186
194
|
# get initial costs for queries
|
187
195
|
calculate_plan(queries)
|
188
196
|
explainable_queries = queries.select { |q| q.plans.any? && q.high_cost? }
|
@@ -228,7 +236,9 @@ module Dexter
|
|
228
236
|
calculate_plan(explainable_queries)
|
229
237
|
end
|
230
238
|
|
231
|
-
|
239
|
+
queries.each do |query|
|
240
|
+
query.candidates = candidates
|
241
|
+
end
|
232
242
|
end
|
233
243
|
|
234
244
|
def find_columns(plan)
|
@@ -282,9 +292,8 @@ module Dexter
|
|
282
292
|
query_indexes
|
283
293
|
end
|
284
294
|
|
285
|
-
def determine_indexes(queries,
|
295
|
+
def determine_indexes(queries, tables)
|
286
296
|
new_indexes = {}
|
287
|
-
index_name_to_columns = candidates.invert
|
288
297
|
|
289
298
|
# filter out existing indexes
|
290
299
|
# this must happen at end of process
|
@@ -313,11 +322,11 @@ module Dexter
|
|
313
322
|
cost_savings2 = new_cost > 100 && new_cost2 < new_cost * savings_ratio
|
314
323
|
|
315
324
|
key = cost_savings2 ? 2 : 1
|
316
|
-
query_indexes = hypo_indexes_from_plan(
|
325
|
+
query_indexes = hypo_indexes_from_plan(query.candidates, query.plans[key], index_set)
|
317
326
|
|
318
327
|
# likely a bad suggestion, so try single column
|
319
328
|
if cost_savings2 && query_indexes.size > 1
|
320
|
-
query_indexes = hypo_indexes_from_plan(
|
329
|
+
query_indexes = hypo_indexes_from_plan(query.candidates, query.plans[1], index_set)
|
321
330
|
cost_savings2 = false
|
322
331
|
end
|
323
332
|
|
@@ -390,8 +399,8 @@ module Dexter
|
|
390
399
|
|
391
400
|
# TODO optimize
|
392
401
|
if @log_level.start_with?("debug")
|
393
|
-
query.pass1_indexes = hypo_indexes_from_plan(
|
394
|
-
query.pass2_indexes = hypo_indexes_from_plan(
|
402
|
+
query.pass1_indexes = hypo_indexes_from_plan(query.candidates, query.plans[1], index_set)
|
403
|
+
query.pass2_indexes = hypo_indexes_from_plan(query.candidates, query.plans[2], index_set)
|
395
404
|
end
|
396
405
|
end
|
397
406
|
end
|
@@ -595,7 +604,8 @@ module Dexter
|
|
595
604
|
columns_by_table.each do |table, cols|
|
596
605
|
# no reason to use btree index for json columns
|
597
606
|
cols.reject { |c| ["json", "jsonb"].include?(c[:type]) }.permutation(n) do |col_set|
|
598
|
-
|
607
|
+
index_name = create_hypothetical_index(table, col_set)
|
608
|
+
candidates[index_name] = col_set
|
599
609
|
end
|
600
610
|
end
|
601
611
|
end
|
@@ -612,6 +622,7 @@ module Dexter
|
|
612
622
|
information_schema.tables
|
613
623
|
WHERE
|
614
624
|
table_catalog = current_database()
|
625
|
+
AND table_type IN ('BASE TABLE', 'VIEW')
|
615
626
|
SQL
|
616
627
|
result.map { |r| r["table_name"] }
|
617
628
|
end
|
data/lib/dexter/query.rb
CHANGED
@@ -2,7 +2,7 @@ module Dexter
|
|
2
2
|
class Query
|
3
3
|
attr_reader :statement, :fingerprint, :plans
|
4
4
|
attr_writer :tables
|
5
|
-
attr_accessor :missing_tables, :new_cost, :total_time, :calls, :indexes, :suggest_index, :pass1_indexes, :pass2_indexes, :pass3_indexes, :candidate_tables, :tables_from_views
|
5
|
+
attr_accessor :missing_tables, :new_cost, :total_time, :calls, :indexes, :suggest_index, :pass1_indexes, :pass2_indexes, :pass3_indexes, :candidate_tables, :tables_from_views, :candidates
|
6
6
|
|
7
7
|
def initialize(statement, fingerprint = nil)
|
8
8
|
@statement = statement
|
data/lib/dexter/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pgdexter
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.5.
|
4
|
+
version: 0.5.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andrew Kane
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-04-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: csv
|
@@ -24,6 +24,20 @@ dependencies:
|
|
24
24
|
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: google-protobuf
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "<"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '4'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "<"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '4'
|
27
41
|
- !ruby/object:Gem::Dependency
|
28
42
|
name: pg
|
29
43
|
requirement: !ruby/object:Gem::Requirement
|