Я пытаюсь оптимизировать производительность запроса в Active Record. Раньше я делал два SQL-запроса, и это можно было сделать за один.
Это таблицы, к которым я запускаю запросы:
# Table name: notifications
#
# id :integer not null, primary key
# content :text(65535)
# position :integer
# Table name: dismissed_notifications
#
# id :integer not null, primary key
# notification_id :integer
# user_id :integer
Это существующий запрос:
where.not(id: user.dismissed_notifications.pluck(:id))
который производит:
SELECT `dismissed_notifications`.`id` FROM `dismissed_notifications` WHERE `dismissed_notifications`.`user_id` = 655
SELECT `notifications`.* FROM `notifications` WHERE (`notifications`.`id` != 1)
Это SQL, который я хотел бы получить, который возвращает те же записи:
select *
from notifications n
where not exists(
select 1
from dismissed_notifications dn
where dn.id = n.id
and dn.user_id = 655)
Вы можете написать not exists
Запрос, как показано ниже.
where('NOT EXISTS (' + user.dismissed_notifications.where('dismissed_notifications.id = notifications.id').to_sql + ')')
ИЛИ
Существует также другой способ уменьшить количество запросов — использовать select
вместо pluck
, он создаст подзапрос вместо извлечения записей из базы данных. Подзапросы Rails ActiveRecord
where.not(id: user.dismissed_notifications.select(:id))
Который будет генерировать ниже SQL-запрос
SELECT `notifications`.*
FROM `notifications`
WHERE (
`notifications`.`id` NOT IN
(SELECT `dismissed_notifications`.`id`
FROM `dismissed_notifications`
WHERE `dismissed_notifications`.`user_id` = 655
)
)
Выглядит как задача для
outer_join
для меня