Merge the 100 favorite subtables into a single table. Previously the favorites table was partitioned by user id into 100 subtables to try to make searching by user id faster. This wasn't really necessary and probably slower than just making an index on (favorites.user_id, favorites.id) to satisfy ordfav searches. BTree indexes are logarithmic so dividing an index by 100 doesn't make it 100 times faster to search; instead it just removes a layer or two from the tree. This also adds a uniqueness index on (user_id, post_id) to prevent duplicate favorites. Previously we had to check for duplicates at the application layer, which required careful locking to do it correctly. Finally, this adds an index on favorites.id, which was surprisingly missing before. This made ordering and deleting favorites by id really slow because it degraded to a sequential scan.
32 lines
1.2 KiB
Ruby
32 lines
1.2 KiB
Ruby
require_relative "20100211181944_create_favorites.rb"
|
|
|
|
class MergeFavoritesTables < ActiveRecord::Migration[6.1]
|
|
def up
|
|
execute "set statement_timeout = 0"
|
|
|
|
execute "CREATE TABLE favorites_copy AS SELECT id, user_id, post_id FROM favorites"
|
|
revert CreateFavorites
|
|
rename_table :favorites_copy, :favorites
|
|
|
|
add_index :favorites, [:user_id, :post_id], unique: true, if_not_exists: true
|
|
add_index :favorites, [:user_id, :id], if_not_exists: true
|
|
add_index :favorites, :post_id, if_not_exists: true
|
|
change_column_null :favorites, :user_id, false
|
|
change_column_null :favorites, :post_id, false
|
|
|
|
execute "ALTER TABLE favorites ADD PRIMARY KEY (id)"
|
|
max_id = Favorite.maximum(:id).to_i
|
|
execute "CREATE SEQUENCE IF NOT EXISTS favorites_id_seq START #{max_id+1} OWNED BY favorites.id"
|
|
execute "ALTER TABLE favorites ALTER COLUMN id SET DEFAULT nextval('favorites_id_seq')"
|
|
end
|
|
|
|
def down
|
|
execute "set statement_timeout = 0"
|
|
|
|
rename_table :favorites, :favorites_copy
|
|
run CreateFavorites
|
|
execute "INSERT INTO favorites(id, user_id, post_id) SELECT id, user_id, post_id FROM favorites_copy"
|
|
drop_table :favorites_copy
|
|
end
|
|
end
|