Commit d721b719 authored by Mayra Cabrera's avatar Mayra Cabrera

Merge branch 'ab/partitioning-detect-range' into 'master'

Detect ranges for time-space partitioning

See merge request gitlab-org/gitlab!34652
parents ebad86ba a9a2b82d
...@@ -24,14 +24,25 @@ module Gitlab ...@@ -24,14 +24,25 @@ module Gitlab
# #
# partition_table_by_date :audit_events, :created_at, min_date: Date.new(2020, 1), max_date: Date.new(2020, 6) # partition_table_by_date :audit_events, :created_at, min_date: Date.new(2020, 1), max_date: Date.new(2020, 6)
# #
# Required options are: # Options are:
# :min_date - a date specifying the lower bounds of the partition range # :min_date - a date specifying the lower bounds of the partition range
# :max_date - a date specifying the upper bounds of the partitioning range # :max_date - a date specifying the upper bounds of the partitioning range, defaults to today + 1 month
# #
def partition_table_by_date(table_name, column_name, min_date:, max_date:) # Unless min_date is specified explicitly, we default to
# 1. The minimum value for the partitioning column in the table
# 2. If no data is present yet, the current month
def partition_table_by_date(table_name, column_name, min_date: nil, max_date: nil)
assert_table_is_allowed(table_name) assert_table_is_allowed(table_name)
assert_not_in_transaction_block(scope: ERROR_SCOPE) assert_not_in_transaction_block(scope: ERROR_SCOPE)
max_date ||= Date.today + 1.month
min_date ||= connection.select_one(<<~SQL)['minimum'] || max_date - 1.month
SELECT date_trunc('MONTH', MIN(#{column_name})) AS minimum
FROM #{table_name}
SQL
raise "max_date #{max_date} must be greater than min_date #{min_date}" if min_date >= max_date raise "max_date #{max_date} must be greater than min_date #{min_date}" if min_date >= max_date
primary_key = connection.primary_key(table_name) primary_key = connection.primary_key(table_name)
......
...@@ -173,6 +173,77 @@ RSpec.describe Gitlab::Database::PartitioningMigrationHelpers::TableManagementHe ...@@ -173,6 +173,77 @@ RSpec.describe Gitlab::Database::PartitioningMigrationHelpers::TableManagementHe
'202003' => ["'2020-03-01 00:00:00'", "'2020-04-01 00:00:00'"] '202003' => ["'2020-03-01 00:00:00'", "'2020-04-01 00:00:00'"]
}) })
end end
context 'when min_date is not given' do
let(:template_table) { :todos }
context 'with records present already' do
before do
create(:todo, created_at: Date.parse('2019-11-05'))
end
it 'creates a partition spanning over each month from the first record' do
migration.partition_table_by_date template_table, partition_column, max_date: max_date
expect_range_partitions_for(partitioned_table, {
'000000' => ['MINVALUE', "'2019-11-01 00:00:00'"],
'201911' => ["'2019-11-01 00:00:00'", "'2019-12-01 00:00:00'"],
'201912' => ["'2019-12-01 00:00:00'", "'2020-01-01 00:00:00'"],
'202001' => ["'2020-01-01 00:00:00'", "'2020-02-01 00:00:00'"],
'202002' => ["'2020-02-01 00:00:00'", "'2020-03-01 00:00:00'"],
'202003' => ["'2020-03-01 00:00:00'", "'2020-04-01 00:00:00'"]
})
end
end
context 'without data' do
it 'creates the catchall partition plus two actual partition' do
migration.partition_table_by_date template_table, partition_column, max_date: max_date
expect_range_partitions_for(partitioned_table, {
'000000' => ['MINVALUE', "'2020-02-01 00:00:00'"],
'202002' => ["'2020-02-01 00:00:00'", "'2020-03-01 00:00:00'"],
'202003' => ["'2020-03-01 00:00:00'", "'2020-04-01 00:00:00'"]
})
end
end
end
context 'when max_date is not given' do
it 'creates partitions including the next month from today' do
today = Date.new(2020, 5, 8)
Timecop.freeze(today) do
migration.partition_table_by_date template_table, partition_column, min_date: min_date
expect_range_partitions_for(partitioned_table, {
'000000' => ['MINVALUE', "'2019-12-01 00:00:00'"],
'201912' => ["'2019-12-01 00:00:00'", "'2020-01-01 00:00:00'"],
'202001' => ["'2020-01-01 00:00:00'", "'2020-02-01 00:00:00'"],
'202002' => ["'2020-02-01 00:00:00'", "'2020-03-01 00:00:00'"],
'202003' => ["'2020-03-01 00:00:00'", "'2020-04-01 00:00:00'"],
'202004' => ["'2020-04-01 00:00:00'", "'2020-05-01 00:00:00'"],
'202005' => ["'2020-05-01 00:00:00'", "'2020-06-01 00:00:00'"],
'202006' => ["'2020-06-01 00:00:00'", "'2020-07-01 00:00:00'"]
})
end
end
end
context 'without min_date, max_date' do
it 'creates partitions for the current and next month' do
current_date = Date.new(2020, 05, 22)
Timecop.freeze(current_date.to_time) do
migration.partition_table_by_date template_table, partition_column
expect_range_partitions_for(partitioned_table, {
'000000' => ['MINVALUE', "'2020-05-01 00:00:00'"],
'202005' => ["'2020-05-01 00:00:00'", "'2020-06-01 00:00:00'"],
'202006' => ["'2020-06-01 00:00:00'", "'2020-07-01 00:00:00'"]
})
end
end
end
end end
describe 'keeping data in sync with the partitioned table' do describe 'keeping data in sync with the partitioned table' do
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment