It is a time to do table partition when the data size of the table cannot fit in memory. Partitioning refers to splitting what is logically one large table into smaller physical pieces. It makes it more efficient to query small amount of data in a large table.

Suppose we have many shops and each shop has many orders. We want to do partition in order table by every 100 shop. That means orders of shop 1 ~ 100 are saved in partition 1. And orders of shop 101 ~ 200 are saved in partition 2.

First create shops table and orders table. Then create table orders_partition1, which inherits orders table and add a check to check shop id is between 1 to 100. Remember to add index to orders_partition1. Table inheritance doesn’t inherit index.

class CreateTables < ActiveRecord::Migration
  def change
    create_table :shops
    create_table :orders do |t|
      t.references :shop
    end

    sql = %(
        CREATE TABLE IF NOT EXISTS orders_partition1 (
          CHECK ( shop_id BETWEEN 1 AND 100 )
        ) INHERITS (orders);
      )
    ActiveRecord::Base.connection.execute(sql)
    add_index 'orders_partition1', :shop_id
  end
end

The order class has a class method - partition_class, which returns new anonymous class inherits orders but table is point to the partition.

class Order < ActiveRecord::Base
  belongs_to :shop

  def self.partition_class(partition)
    Class.new(Order) do
      self.table_name = "orders_partition#{partition}"
    end
  end
end

Order.partition_class(1).table_name
# => orders_partition1

Define orders instance method in shop class, which decides the partition by shop id. Add we can use it as normal has_many relation!

class Shop < ActiveRecord::Base
  def orders
    Order.partition_class(orders_partition).where(shop_id: id)
  end

  def orders_partition
    (id / 100) + 1
  end
end

shop = Shop.find 1
shop.orders
# SELECT orders FROM orders_partition1 WHERE shop_id is 1;
shop.orders.create
# INSERT INTO orders_partition1 shop_id VALUES 1;

Reference

PostgreSQL Partitioning: https://www.postgresql.org/docs/9.4/static/ddl-partitioning.html


darren987469