partitioner_pg 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/README.md +63 -20
- data/lib/partitioner_pg/separation_type/month.rb +78 -5
- data/lib/partitioner_pg/version.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: e30a831e9e29196be95988158811a18398422ae7bd0ad6301906778f4f1fcd0a
|
4
|
+
data.tar.gz: 134c8445b3610c98365fca4b0a066ef668b368592b4094c53479acca5961ef33
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7630fafde31ad687310dfce98bfa55719cf52038ec6a293be0bf484b875d0902f782d038ab188e8bfe823ac7f07f5d60295a476ad520d5d35e02ec71f5be2e6b
|
7
|
+
data.tar.gz: 2c940f85492295a3eb8cd23bc324c397991cd6bebacb0a360f7b07fcb3419bdd18defbf25f3f228e9a20c9ddf656b1d5ae3550b63d6222e3cf485d258bda7a71
|
data/README.md
CHANGED
@@ -1,36 +1,79 @@
|
|
1
|
-
#
|
1
|
+
# PartitionerPg
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
TODO: Delete this and the text above, and describe your gem
|
3
|
+
It's a gem for a partitioning Postgresql tables in Ruby on Rails.
|
4
|
+
Now gem can help you with partitioning tables by months. New table for each month.
|
6
5
|
|
7
6
|
## Installation
|
8
7
|
|
9
8
|
Add this line to your application's Gemfile:
|
10
9
|
|
11
10
|
```ruby
|
12
|
-
gem '
|
11
|
+
gem 'partitioner_pg'
|
13
12
|
```
|
14
13
|
|
15
|
-
And then execute:
|
16
|
-
|
17
|
-
$ bundle
|
18
|
-
|
19
|
-
Or install it yourself as:
|
20
|
-
|
21
|
-
$ gem install partitioner
|
22
|
-
|
23
14
|
## Usage
|
24
15
|
|
25
|
-
|
26
|
-
|
27
|
-
|
16
|
+
1) Include PartitionerPg into your model: `include PartitionerPg`. Also, you can specify parting column and some indexes.
|
17
|
+
Example:
|
18
|
+
```ruby
|
19
|
+
class YourModelName < ActiveRecord::Base
|
20
|
+
include PartitionerPg
|
21
|
+
|
22
|
+
# Point date or datetime column which will be used for monthly partitioning. Optional (:created_at uses by default)
|
23
|
+
def self.parting_column
|
24
|
+
:date
|
25
|
+
end
|
26
|
+
|
27
|
+
# List of indexes. Names of indexes will be generated by active migration. Optional.
|
28
|
+
def self.partition_table_indexes
|
29
|
+
[
|
30
|
+
%w[column1 column2]
|
31
|
+
]
|
32
|
+
end
|
33
|
+
|
34
|
+
# Map of indexes. Full name of named index will be generated as "index_[partition_name]_[name_of_index_from_map]". Optional.
|
35
|
+
def self.partition_table_named_indexes
|
36
|
+
{
|
37
|
+
:three_cols => %w[column1 column2 column3]
|
38
|
+
}
|
39
|
+
end
|
40
|
+
|
41
|
+
# List of unique indexes. Names of indexes wiil be generated by active migration. Optional.
|
42
|
+
def self.partition_table_unique_indexes
|
43
|
+
[
|
44
|
+
%w[column1 column2 column3 column4]
|
45
|
+
]
|
46
|
+
end
|
47
|
+
|
48
|
+
# Map of named unique indexes. Optional.
|
49
|
+
def self.partition_table_named_unique_indexes
|
50
|
+
{
|
51
|
+
:uniq => %w[column5 column6 column7]
|
52
|
+
}
|
53
|
+
end
|
54
|
+
end
|
55
|
+
```
|
56
|
+
2) Create migration and add some instructions to it. Generate migration:
|
28
57
|
|
29
|
-
|
58
|
+
```
|
59
|
+
rails g migration make_partitioning_of_you_table
|
60
|
+
```
|
30
61
|
|
31
|
-
|
62
|
+
add instructions to migration:
|
32
63
|
|
33
|
-
|
64
|
+
```ruby
|
65
|
+
class YouMigrationClassName
|
66
|
+
def change
|
67
|
+
YourModel.create_partitioning_by_month_trigger_sql
|
68
|
+
YourModel.create_month_table
|
69
|
+
YourModel.create_next_month_table
|
70
|
+
end
|
71
|
+
end
|
72
|
+
```
|
34
73
|
|
35
|
-
|
74
|
+
3) For correct work you need to create next partition every month.
|
75
|
+
We recommend you to create a rake task and run it once a month by crontab. Code for a rake task:
|
36
76
|
|
77
|
+
```ruby
|
78
|
+
YourModel.create_next_month_table
|
79
|
+
```
|
@@ -12,12 +12,18 @@ module PartitionerPg
|
|
12
12
|
def create_month_table(date=Date.today)
|
13
13
|
date_start = date.at_beginning_of_month
|
14
14
|
date_end = date.at_beginning_of_month.next_month
|
15
|
-
|
16
|
-
|
15
|
+
partition_table_name = name_of_partition_table(date)
|
16
|
+
sql = "CREATE TABLE IF NOT EXISTS #{partition_table_name} (
|
17
|
+
CHECK ( #{parting_column} >= DATE('#{date_start}') AND #{parting_column} < DATE('#{date_end}') )
|
17
18
|
) INHERITS (#{table_name});"
|
18
19
|
execute_sql(sql)
|
19
|
-
sql = "ALTER TABLE #{
|
20
|
+
sql = "ALTER TABLE #{partition_table_name} ADD PRIMARY KEY (id);"
|
20
21
|
execute_sql(sql)
|
22
|
+
|
23
|
+
create_partition_indexes(partition_table_name)
|
24
|
+
create_partition_named_indexes(partition_table_name)
|
25
|
+
create_partition_unique_indexes(partition_table_name)
|
26
|
+
create_partition_named_unique_indexes(partition_table_name)
|
21
27
|
end
|
22
28
|
|
23
29
|
def drop_month_table(date=Date.today)
|
@@ -33,8 +39,8 @@ module PartitionerPg
|
|
33
39
|
curM varchar(2);
|
34
40
|
tbl varchar(30);
|
35
41
|
BEGIN
|
36
|
-
select cast(DATE_PART('year', new
|
37
|
-
select lpad(cast(DATE_PART('month', new
|
42
|
+
select cast(DATE_PART('year', new.#{parting_column}) as varchar) into curY;
|
43
|
+
select lpad(cast(DATE_PART('month', new.#{parting_column}) as varchar), 2, '0') into curM;
|
38
44
|
tbl := '#{table_name}_y' || curY || 'm' || curM;
|
39
45
|
EXECUTE format('INSERT into %I values ($1.*);', tbl) USING NEW;
|
40
46
|
return NEW;
|
@@ -72,9 +78,76 @@ module PartitionerPg
|
|
72
78
|
DROP FUNCTION #{table_name}_delete_trigger();"
|
73
79
|
end
|
74
80
|
|
81
|
+
def create_partition_indexes(partition_table_name)
|
82
|
+
custom_indexes = partition_table_indexes.presence
|
83
|
+
return unless custom_indexes
|
84
|
+
|
85
|
+
custom_indexes.each { |custom_index| create_custom_index(partition_table_name, custom_index) }
|
86
|
+
end
|
87
|
+
|
88
|
+
def create_partition_named_indexes(partition_table_name)
|
89
|
+
custom_indexes = partition_table_named_indexes.presence
|
90
|
+
return unless custom_indexes
|
91
|
+
|
92
|
+
custom_indexes.map{|name, custom_index|
|
93
|
+
index_name = "index_#{partition_table_name}_#{name}"
|
94
|
+
create_custom_named_index(partition_table_name, custom_index, index_name)
|
95
|
+
}
|
96
|
+
end
|
97
|
+
|
98
|
+
def create_partition_unique_indexes(partition_table_name)
|
99
|
+
custom_unique_indexes = partition_table_unique_indexes.presence
|
100
|
+
return unless custom_unique_indexes
|
101
|
+
|
102
|
+
custom_unique_indexes.each { |custom_index| create_custom_index(partition_table_name, custom_index, true) }
|
103
|
+
end
|
104
|
+
|
105
|
+
def create_partition_named_unique_indexes(partition_table_name)
|
106
|
+
custom_indexes = partition_table_named_unique_indexes.presence
|
107
|
+
return unless custom_indexes
|
108
|
+
|
109
|
+
custom_indexes.map{|name, custom_index|
|
110
|
+
index_name = "index_#{partition_table_name}_#{name}"
|
111
|
+
create_custom_named_index(partition_table_name, custom_index, index_name, true)
|
112
|
+
}
|
113
|
+
end
|
114
|
+
|
115
|
+
def create_custom_index(table_name, index_fields, is_unique = false)
|
116
|
+
ActiveRecord::Migration.add_index table_name, index_fields, unique: is_unique
|
117
|
+
end
|
118
|
+
|
119
|
+
def create_custom_named_index(table_name, index_fields, name, is_unique = false)
|
120
|
+
ActiveRecord::Migration.add_index table_name, index_fields, name: name, unique: is_unique
|
121
|
+
end
|
122
|
+
|
75
123
|
def name_of_partition_table(date=Date.today)
|
76
124
|
date.strftime("#{table_name}_y%Ym%m")
|
77
125
|
end
|
126
|
+
|
127
|
+
# Template method
|
128
|
+
# Column which will determine partition for row (must be date or datetime type). Default value is :created_at
|
129
|
+
def parting_column
|
130
|
+
:created_at
|
131
|
+
end
|
132
|
+
|
133
|
+
# Template method
|
134
|
+
def partition_table_indexes
|
135
|
+
#
|
136
|
+
end
|
137
|
+
|
138
|
+
def partition_table_named_indexes
|
139
|
+
#
|
140
|
+
end
|
141
|
+
|
142
|
+
# Template method
|
143
|
+
def partition_table_unique_indexes
|
144
|
+
#
|
145
|
+
end
|
146
|
+
|
147
|
+
# Template method
|
148
|
+
def partition_table_named_unique_indexes
|
149
|
+
#
|
150
|
+
end
|
78
151
|
end
|
79
152
|
end
|
80
153
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: partitioner_pg
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Aleksander Nikulin
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2018-04-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -76,7 +76,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
76
76
|
version: '0'
|
77
77
|
requirements: []
|
78
78
|
rubyforge_project:
|
79
|
-
rubygems_version: 2.
|
79
|
+
rubygems_version: 2.7.3
|
80
80
|
signing_key:
|
81
81
|
specification_version: 4
|
82
82
|
summary: Gem for a partitoning PG tables
|