Class: PartitionGardener::Strategy::DateRange
Constant Summary
collapse
- DEFAULT_ACTIVE_MONTHS =
12
- DEFAULT_ACTIVE_YEARS =
2
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
#initialize(config) ⇒ DateRange
Returns a new instance of DateRange.
11
12
13
|
# File 'lib/partition_gardener/strategy/date_range.rb', line 11
def initialize(config)
@config = config
end
|
Instance Method Details
#active_window ⇒ Object
15
16
17
18
19
20
21
22
|
# File 'lib/partition_gardener/strategy/date_range.rb', line 15
def active_window
bucket = date_bucket
active_start = DateBucket.beginning_of_bucket(today, bucket)
active_span = active_span_for(bucket)
active_end = DateBucket.add_buckets(active_start, active_span, bucket)
{start: active_start, end: active_end}
end
|
#archive_bucket?(bucket) ⇒ Boolean
134
135
136
|
# File 'lib/partition_gardener/strategy/date_range.rb', line 134
def archive_bucket?(bucket)
beginning_of_bucket(bucket) < active_window[:start]
end
|
#archive_bucket_from_partition_name(partition_name) ⇒ Object
142
143
144
|
# File 'lib/partition_gardener/strategy/date_range.rb', line 142
def archive_bucket_from_partition_name(partition_name)
DateBucket.archive_bucket_from_partition_name(table_name, partition_name, date_bucket)
end
|
#attached_tail_segments ⇒ Object
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
|
# File 'lib/partition_gardener/strategy/date_range.rb', line 39
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
|
#beginning_of_bucket(bucket) ⇒ Object
130
131
132
|
# File 'lib/partition_gardener/strategy/date_range.rb', line 130
def beginning_of_bucket(bucket)
DateBucket.beginning_of_bucket(bucket.to_date, date_bucket)
end
|
#bucket_counts_in_partition(partition_name) ⇒ Object
156
157
158
|
# File 'lib/partition_gardener/strategy/date_range.rb', line 156
def bucket_counts_in_partition(partition_name)
counts_by_bucket_in_partition(partition_name)
end
|
#bucket_where_condition(bucket) ⇒ Object
123
124
125
126
127
128
|
# File 'lib/partition_gardener/strategy/date_range.rb', line 123
def bucket_where_condition(bucket)
partition_key_column = @config[:partition_key_column]
start_range = beginning_of_bucket(bucket)
end_range = end_of_bucket(bucket)
"#{partition_key_column} >= #{connection.quote(start_range)}::date AND #{partition_key_column} < #{connection.quote(end_range)}::date"
end
|
#build_plan ⇒ Object
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
# File 'lib/partition_gardener/strategy/date_range.rb', line 24
def build_plan
window = active_window
heatmap = collect_heatmap(window)
hot_buckets = hot_buckets_in_window(heatmap, window)
segments = Layout::OccupiedWindow.plan_segments(
config: @config,
window: window,
hot_buckets: hot_buckets,
year_bucket: year_bucket?,
tail_slot: method(:tail_slot_name?)
)
Plan::Result.new(segments: segments, hot_buckets: hot_buckets)
end
|
#collect_heatmap(window) ⇒ Object
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
|
# File 'lib/partition_gardener/strategy/date_range.rb', line 55
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)
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
118
119
120
121
|
# File 'lib/partition_gardener/strategy/date_range.rb', line 118
def current_and_future_where_condition(window: active_window)
partition_key_column = @config[:partition_key_column]
"#{partition_key_column} >= #{connection.quote(window[:start])}::date"
end
|
#future_bucket?(bucket) ⇒ Boolean
138
139
140
|
# File 'lib/partition_gardener/strategy/date_range.rb', line 138
def future_bucket?(bucket)
beginning_of_bucket(bucket) > beginning_of_bucket(today)
end
|
#hot_buckets_in_window(heatmap, window) ⇒ Object
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
|
# File 'lib/partition_gardener/strategy/date_range.rb', line 75
def hot_buckets_in_window(heatmap, window)
return [] if rolling_current_layout?
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
102
103
104
105
106
107
108
109
|
# File 'lib/partition_gardener/strategy/date_range.rb', line 102
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
146
147
148
149
150
151
152
153
154
|
# File 'lib/partition_gardener/strategy/date_range.rb', line 146
def segment_for_values_clause(segment)
if segment.range_end == :max
"FROM ('#{segment.range_start}') TO (MAXVALUE)"
elsif segment.hash_partition?
"WITH (modulus #{segment.range_start[:modulus]}, remainder #{segment.range_start[:remainder]})"
else
"FROM ('#{segment.range_start}') TO ('#{segment.range_end}')"
end
end
|
#tail_slot_name?(partition_name) ⇒ Boolean
111
112
113
114
115
116
|
# File 'lib/partition_gardener/strategy/date_range.rb', line 111
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
|