Class: PartitionGardener::Strategy::IntegerRange
Constant Summary
collapse
- DEFAULT_ACTIVE_ID_WIDTH =
10_000_000
- DEFAULT_CURRENT_BAND_SIZE =
1_000_000
- DEFAULT_ARCHIVE_BAND_SIZE =
10_000_000
Instance Method Summary
collapse
#cursor_columns, #partition_key_base
#default_partition_drain_where_condition, #default_partition_required?, #rebalance_default_drain_where_condition
Methods included from Naming
current_partition_name, default_partition_name, future_partition_name, open_partition_name, rebalance_staging_partition_name
Constructor Details
Returns a new instance of IntegerRange.
12
13
14
|
# File 'lib/partition_gardener/strategy/integer_range.rb', line 12
def initialize(config)
@config = config
end
|
Instance Method Details
#active_window ⇒ Object
16
17
18
19
20
|
# File 'lib/partition_gardener/strategy/integer_range.rb', line 16
def active_window
active_lo = @config.fetch(:active_id_lo) { 0 }
active_hi = active_lo + active_id_width
{start: active_lo, end: active_hi}
end
|
#archive_bucket?(bucket) ⇒ Boolean
128
129
130
|
# File 'lib/partition_gardener/strategy/integer_range.rb', line 128
def archive_bucket?(bucket)
bucket < active_window[:start]
end
|
#archive_bucket_from_partition_name(partition_name) ⇒ Object
136
137
138
139
140
141
|
# File 'lib/partition_gardener/strategy/integer_range.rb', line 136
def archive_bucket_from_partition_name(partition_name)
match = partition_name.match(/^#{Regexp.escape(table_name)}_ids_(\d+)_(\d+)$/)
return unless match
match[1].to_i
end
|
#attached_tail_segments ⇒ Object
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
|
# File 'lib/partition_gardener/strategy/integer_range.rb', line 40
def attached_tail_segments
window = active_window
Connection.attached_partitions(table_name).filter_map do |partition|
next if partition.default
next unless managed_tail_partition?(partition.name, window: window)
Plan::Segment.new(
name: partition.name,
range_start: partition.range_start,
range_end: partition.range_end,
kind: segment_kind_for(partition.name, window: window)
)
end
end
|
#bucket_where_condition(bucket) ⇒ Object
122
123
124
125
126
|
# File 'lib/partition_gardener/strategy/integer_range.rb', line 122
def bucket_where_condition(bucket)
partition_key_column = @config[:partition_key_column]
end_range = bucket + current_band_size
"#{partition_key_column} >= #{bucket} AND #{partition_key_column} < #{end_range}"
end
|
#build_plan ⇒ Object
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
|
# File 'lib/partition_gardener/strategy/integer_range.rb', line 22
def build_plan
window = active_window
heatmap = collect_heatmap(window)
hot_buckets = hot_buckets_in_window(heatmap, window)
segments = Layout::ZoneSegments.build_filler_and_hot_segments(
table_name: table_name,
buckets: each_bucket_in_range(window[:start], window[:end]),
hot_buckets: hot_buckets,
active_start: window[:start],
active_end: window[:end],
hot_bucket_name: method(:hot_bucket_partition_name),
bucket_end: ->(bucket) { [bucket + current_band_size, window[:end]].min }
)
Plan::Result.new(segments: segments, hot_buckets: hot_buckets)
end
|
#collect_heatmap(window) ⇒ Object
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
|
# File 'lib/partition_gardener/strategy/integer_range.rb', line 56
def collect_heatmap(window)
bucket_counts = Hash.new(0)
dedicated_partition_counts = {}
dedicated_partitions = hot_bucket_partitions_in_window(window).to_h
heatmap_source_partitions(window).each do |partition_name|
counts = counts_by_bucket_in_partition(partition_name, window)
counts.each { |bucket, count| bucket_counts[bucket] += count }
bucket = dedicated_partitions[partition_name]
dedicated_partition_counts[bucket] = counts.values.sum if bucket
end
{
bucket_counts: bucket_counts,
default_rows: default_row_count,
dedicated_partition_counts: dedicated_partition_counts
}
end
|
#current_and_future_where_condition(window: active_window) ⇒ Object
117
118
119
120
|
# File 'lib/partition_gardener/strategy/integer_range.rb', line 117
def current_and_future_where_condition(window: active_window)
partition_key_column = @config[:partition_key_column]
"#{partition_key_column} >= #{window[:start]}"
end
|
#current_band_size ⇒ Object
156
157
158
|
# File 'lib/partition_gardener/strategy/integer_range.rb', line 156
def current_band_size
@config.fetch(:current_band_size, DEFAULT_CURRENT_BAND_SIZE)
end
|
#future_bucket?(bucket) ⇒ Boolean
132
133
134
|
# File 'lib/partition_gardener/strategy/integer_range.rb', line 132
def future_bucket?(bucket)
bucket >= active_window[:end]
end
|
#hot_bucket_partition_name(bucket) ⇒ Object
151
152
153
154
|
# File 'lib/partition_gardener/strategy/integer_range.rb', line 151
def hot_bucket_partition_name(bucket)
end_range = [bucket + current_band_size, active_window[:end]].min
"#{table_name}_ids_#{bucket}_#{end_range}"
end
|
#hot_buckets_in_window(heatmap, window) ⇒ Object
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
|
# File 'lib/partition_gardener/strategy/integer_range.rb', line 76
def hot_buckets_in_window(heatmap, window)
hot_buckets = Set.new
heatmap[:bucket_counts].each do |bucket, row_count|
next unless bucket_in_window?(bucket, window)
next unless row_count >= split_row_threshold
hot_buckets << bucket
end
dedicated_counts = heatmap.fetch(:dedicated_partition_counts, {})
hot_bucket_partitions_in_window(window).each do |_partition_name, bucket|
row_count = dedicated_counts[bucket]
next if row_count.nil?
if row_count >= split_row_threshold
hot_buckets << bucket
else
hot_buckets.delete(bucket)
end
end
hot_buckets.sort
end
|
#managed_tail_partition_names(window: active_window) ⇒ Object
101
102
103
104
105
106
107
108
|
# File 'lib/partition_gardener/strategy/integer_range.rb', line 101
def managed_tail_partition_names(window: active_window)
Connection.attached_partitions(table_name).filter_map do |partition|
next if partition.default
next unless managed_tail_partition?(partition.name, window: window)
partition.name
end
end
|
#segment_for_values_clause(segment) ⇒ Object
143
144
145
146
147
148
149
|
# File 'lib/partition_gardener/strategy/integer_range.rb', line 143
def segment_for_values_clause(segment)
if segment.range_end == :max
"FROM (#{segment.range_start}) TO (MAXVALUE)"
else
"FROM (#{segment.range_start}) TO (#{segment.range_end})"
end
end
|
#tail_slot_name?(partition_name) ⇒ Boolean
110
111
112
113
114
115
|
# File 'lib/partition_gardener/strategy/integer_range.rb', line 110
def tail_slot_name?(partition_name)
partition_name == current_partition_name(table_name) ||
partition_name == open_partition_name(table_name) ||
partition_name == future_partition_name(table_name) ||
partition_name.match?(/^#{Regexp.escape(table_name)}_open_\d+$/)
end
|