业务中有一个表按列创建了普通单列索引,但是没有唯一性约束,现在想要为这个字段添加唯一性索引。
比如我们需要对通知记录表 notifications
的 order_id
字段添加唯一约束,但是这个表已经有了 order_id
的普通索引。
直接添加唯一索引,当数据库里面已经存在order_id
重复记录的时候会报错。
Duplicate entry '1' for key 'index_notifications_on_order_id'
如果直接删除索引,再新建索引,在索引新建完成前,业务会受到影响,涉及到按order_id
查询记录的会导致全表扫描,影响数据库性能
以 notifications
表为例
order_id
字段重复的记录def delete_duplicated_records
# 查找存在重复的记录
dup_order_ids = ::Notification.group(:order_id).having('COUNT(*) > 1').pluck(:order_id)
dup_order_ids.each_slice(500) do |order_ids|
not_remove_order_ids = ::Notification.where(order_id: order_ids).group(:order_id).having('COUNT(*) > 1').pluck('MIN(id)')
Notification.where(order_id: order_ids).where.not(id: not_remove_order_ids).destroy_all
end
end
rename_index :notifications, :index_notifications_on_order_id, :non_uniq_index_notifications_on_order_id
add_index :notifications, :order_id, unique: true
remove_index :notifications, name: :non_uniq_index_notifications_on_order_id, column: :order_id