Таким образом, общая проблема производительности связана с операциями вычисления, которые происходят вне базы данных, например:
(Device.in_dhcp_range.select("devices.id") +
Device.alternate_aws.select("devices.id")).uniq
- Device.reserved)
Это выполняет 3 запроса, а затем использует Array
(или Array
как) методына ActiveRecord::Relation
s, чтобы вернуть список Device
s для выбора.Это приведет к большому количеству вычислений, а также к очень большому предложению IN
в запросе (которое в какой-то момент превысит количество символов, выделенных для оператора SQL)
Вместо этого вы должны поместить все этоработать с самой базой данных, используя подзапросы для построения предложения where, например:
scope :dhcp_full_calculation, -> {
where.not(id: Device.reserved.select(:id) ).where(
id: Device.select(:id).where(id:
Device.in_dhcp_range.select(:id)
).or(
Device.select(:id).where(
id: Device.alternate_aws.select(:id)
)
)
)
}
Это сгенерирует запрос, похожий на:
SELECT
devices.*
FROM
devices
WHERE
devices.id NOT IN (
SELECT devices.id FROM [YOUR RESERVED QUERY])
AND devices.id IN (
SELECT devices.id
FROM devices
WHERE
devices.id IN ( SELECT devices.id FROM [YOUR IN DHCP RANGE QUERY])
OR devices.id IN ( SELECT devices.id FROM [YOUR ALTERNATE AWS QUERY])
)