Использование Rails и Postgres.
У меня есть 3 таблицы (назовем их «производители», «вертолеты» и «лодки»).Модель производителя связана с has_many для вертолета (через таблицу и модель "factory_helicopters") и с has_many для лодок (через таблицу и модель "factory_boats").
На странице отображения я должен отобразить уникальных производителей, которые либоподключены к вертолету (который имеет один из «helicopter_ids») или подключены к лодке (который имеет один из «boat_ids»).
Более того, ассоциация «вертолет» имеет более высокий приоритет, поэтому мы должны фильтровать только тепроизводители, у которых либо есть «вертолет» с заданным helicopter_id, либо нет «вертолета» вообще.
Это вопрос, который я придумал, но он очень медленный - запрос занимает несколько секунд (таблицы имеют почти 1 милзаписывает каждый)
result = Manufacturer.distinct(:id)
.left_outer_joins(:manufacturer_helicopters, :manufacturer_boats)
.where('helicopter_id IN (?) OR boat_id IN (?)', helicopter_ids, boat_ids)
result.where('manufacturer_helicopters.helicopter_id = ? OR manufacturer_helicopters.helicopter_id IS NULL', helicopter_id)
Буду очень признателен за любые предложения по улучшению производительности.
РЕДАКТИРОВАТЬ Вот объяснение
Unique (cost=104750.30..115799.60 rows=184155 width=384)
-> Sort (cost=104750.30..105210.69 rows=184155 width=384)
Sort Key: manufacturer.id, manufacturer.full_name, manufacturer.serial_number, manufacturer.contact_email, manufacturer.pending, manufacturer.created_at, manufacturer.updated_at, manufacturer.in_production, manufacturer.in_planning, manufacturer.web_url, manufacturer.mobile_url, manufacturer.country, manufacturer.city, manufacturer.zip_code, manufacturer.logo, manufacturer.street, manufacturer.address, manufacturer.last_manufactured_at, manufacturer.archived, manufacturer.external_manufacturer_id, manufacturer.external_serial_number, manufacturer.distributor_id, manufacturer.visible
-> Merge Left Join (cost=1.35..24441.43 rows=184155 width=384)
Merge Cond: (manufacturer.id = manufacturer_helicopter.helicopter_id)
Filter: ((manufacturer_helicopter.helicopter_id = 4) OR (manufacturer_boat.boat_id = 1))
-> Merge Left Join (cost=1.06..19442.76 rows=260211 width=388)
Merge Cond: (manufacturer.id = manufacturer_boat.boat_id)
-> Index Scan using manufacturer_pkey on manufacturers (cost=0.42..11437.12 rows=260211 width=384)
-> Index Scan using manufacturer_on_boat_id_boat on manufacturer_boat (cost=0.42..5352.52 rows=160207 width=8)
-> Index Scan using index_manufacturer_helicopter_on_helicopter_id on manufacturer_helicopter (cost=0.29..3343.37 rows=100005 width=8)