PERF: Use native postgres upsert for ApplicationRequest (#20706)
Using `create_or_find_by!`, followed by `update_all!` requires two or three queries (two when the row doesn't already exist, three when it does). Instead, we can use postgres's native `INSERT ... ON CONFLICT ... DO UPDATE SET` feature to do the logic in a single atomic call.
This commit is contained in:
parent
6b5743ba3c
commit
303f97ce89
|
@ -32,20 +32,14 @@ class ApplicationRequest < ActiveRecord::Base
|
|||
end
|
||||
|
||||
def self.write_cache!(req_type, count, date)
|
||||
id = req_id(date, req_type)
|
||||
where(id: id).update_all(["count = count + ?", count])
|
||||
end
|
||||
|
||||
def self.req_id(date, req_type, retries = 0)
|
||||
req_type_id = req_types[req_type]
|
||||
|
||||
create_or_find_by!(date: date, req_type: req_type_id).id
|
||||
rescue StandardError # primary key violation
|
||||
if retries == 0
|
||||
req_id(date, req_type, 1)
|
||||
else
|
||||
raise
|
||||
end
|
||||
DB.exec(<<~SQL, date: date, req_type_id: req_type_id, count: count)
|
||||
INSERT INTO application_requests (date, req_type, count)
|
||||
VALUES (:date, :req_type_id, :count)
|
||||
ON CONFLICT (date, req_type)
|
||||
DO UPDATE SET count = application_requests.count + excluded.count
|
||||
SQL
|
||||
end
|
||||
|
||||
def self.stats
|
||||
|
|
Loading…
Reference in New Issue