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
139
140
141
|
# File 'lib/partition_gardener/strategy/date_range.rb', line 139
def archive_bucket?(bucket)
beginning_of_bucket(bucket) < active_window[:start]
end
|
#archive_bucket_from_partition_name(partition_name) ⇒ Object
147
148
149
|
# File 'lib/partition_gardener/strategy/date_range.rb', line 147
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
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
|
# File 'lib/partition_gardener/strategy/date_range.rb', line 48
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_counts_in_partition(partition_name) ⇒ Object
161
162
163
|
# File 'lib/partition_gardener/strategy/date_range.rb', line 161
def bucket_counts_in_partition(partition_name)
counts_by_bucket_in_partition(partition_name)
end
|
#bucket_where_condition(bucket) ⇒ Object
132
133
134
135
136
137
|
# File 'lib/partition_gardener/strategy/date_range.rb', line 132
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
38
39
40
41
42
43
44
45
46
|
# 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 = if year_bucket?
Layout::CalendarYear.build_segments(
config: @config,
active_start: window[:start],
active_end: window[:end],
hot_years: hot_buckets
)
else
Layout::SlidingWindow.build_segments(
config: @config,
active_start: window[:start],
active_end: window[:end],
hot_months: hot_buckets
)
end
Plan::Result.new(segments: segments, hot_buckets: hot_buckets)
end
|
#collect_heatmap(window) ⇒ Object
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
|
# File 'lib/partition_gardener/strategy/date_range.rb', line 64
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
127
128
129
130
|
# File 'lib/partition_gardener/strategy/date_range.rb', line 127
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
143
144
145
|
# File 'lib/partition_gardener/strategy/date_range.rb', line 143
def future_bucket?(bucket)
beginning_of_bucket(bucket) > beginning_of_bucket(today)
end
|
#hot_buckets_in_window(heatmap, window) ⇒ Object
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
|
# File 'lib/partition_gardener/strategy/date_range.rb', line 84
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
111
112
113
114
115
116
117
118
|
# File 'lib/partition_gardener/strategy/date_range.rb', line 111
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
151
152
153
154
155
156
157
158
159
|
# File 'lib/partition_gardener/strategy/date_range.rb', line 151
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
120
121
122
123
124
125
|
# File 'lib/partition_gardener/strategy/date_range.rb', line 120
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
|