This project is archived and is in readonly mode.
Optimization of construct_finder_sql_with_included_associations(options, join_dependency) ActiveRecord::Associations::ClassMethods
Reported by Igor Alexandrov | February 11th, 2011 @ 09:35 AM
Hello.
I found that method
construct_finder_sql_with_included_associations(options,
join_dependency) of Rails 2.3 is not optimal when called from
find() method with :order, :include and :limit options. It adds
unnecessary checks in WHERE clause after load IDs for limited eager
loading.
If we have already found needed IDs during limited eager loading, we don't need additional checks in WHERE clause.
Example.
Before patch
Education::Pc Load IDs For Limited Eager Loading (4.7ms)
SELECT FROM (SELECT DISTINCT ON ("pcs".id) "pcs".id, COALESCE(pcs.min_cost, pcs.max_cost) AS alias_0 FROM "pcs" WHERE ((SELECT COUNT() FROM metro_stations_pcs c WHERE c.metro_station_id IN ('57') AND c.pc_id = pcs.id) > 0 AND (SELECT COUNT(*) FROM pcs_durations c WHERE c.duration_id IN ('4') AND c.pc_id = pcs.id) > 0) ) AS id_list ORDER BY id_list.alias_0 LIMIT 20 OFFSET 0
Education::Pc Load Including Associations (2.3ms)
SELECT "pcs"."id" AS t0_r0, "pcs"."name" AS t0_r1, "pcs"."university_id" AS t0_r2, "pcs"."has_distance_learning" AS t0_r3, "pcs"."has_sse_preparation" AS t0_r4, "pcs"."moscow_administrative_district" AS t0_r5, "pcs"."min_cost" AS t0_r6, "pcs"."max_cost" AS t0_r7, "pcs"."address" AS t0_r8, "pcs"."phones" AS t0_r9, "pcs"."emails" AS t0_r10, "pcs"."website" AS t0_r11, "pcs"."description" AS t0_r12, "pcs"."entering_information" AS t0_r13, "pcs"."cost_information" AS t0_r14, "pcs"."duration" AS t0_r15, "pcs"."created_at" AS t0_r16, "pcs"."updated_at" AS t0_r17, "metro_stations"."id" AS t1_r0, "metro_stations"."name" AS t1_r1, "metro_stations"."created_at" AS t1_r2, "metro_stations"."updated_at" AS t1_r3, "metro_stations"."universities_count" AS t1_r4, "metro_stations"."colleges_count" AS t1_r5, "metro_stations"."schools_count" AS t1_r6, "metro_stations"."kindergartens_count" AS t1_r7, "metro_stations"."pcs_count" AS t1_r8, "metro_stations"."secs_count" AS t1_r9 FROM "pcs" LEFT OUTER JOIN "metro_stations_pcs" ON "metro_stations_pcs".pc_id = "pcs".id LEFT OUTER JOIN "metro_stations" ON "metro_stations".id = "metro_stations_pcs".metro_station_id WHERE ((SELECT COUNT() FROM metro_stations_pcs c WHERE c.metro_station_id IN ('57') AND c.pc_id = pcs.id) > 0 AND (SELECT COUNT() FROM pcs_durations c WHERE c.duration_id IN ('4') AND c.pc_id = pcs.id) > 0) AND "pcs".id IN (469) ORDER BY COALESCE(pcs.min_cost, pcs.max_cost) ASC
Look at WHERE clause of last query
After patch Education::Pc Load Including Associations
(1.7ms)
SELECT "pcs"."id" AS t0_r0, "pcs"."name" AS t0_r1,
"pcs"."university_id" AS t0_r2, "pcs"."has_distance_learning" AS
t0_r3, "pcs"."has_sse_preparation" AS t0_r4,
"pcs"."moscow_administrative_district" AS t0_r5, "pcs"."min_cost"
AS t0_r6, "pcs"."max_cost" AS t0_r7, "pcs"."address" AS t0_r8,
"pcs"."phones" AS t0_r9, "pcs"."emails" AS t0_r10, "pcs"."website"
AS t0_r11, "pcs"."description" AS t0_r12,
"pcs"."entering_information" AS t0_r13, "pcs"."cost_information" AS
t0_r14, "pcs"."duration" AS t0_r15, "pcs"."created_at" AS t0_r16,
"pcs"."updated_at" AS t0_r17, "metro_stations"."id" AS t1_r0,
"metro_stations"."name" AS t1_r1, "metro_stations"."created_at" AS
t1_r2, "metro_stations"."updated_at" AS t1_r3,
"metro_stations"."universities_count" AS t1_r4,
"metro_stations"."colleges_count" AS t1_r5,
"metro_stations"."schools_count" AS t1_r6,
"metro_stations"."kindergartens_count" AS t1_r7,
"metro_stations"."pcs_count" AS t1_r8,
"metro_stations"."secs_count" AS t1_r9 FROM "pcs" LEFT OUTER JOIN
"metro_stations_pcs" ON "metro_stations_pcs".pc_id = "pcs".id LEFT
OUTER JOIN "metro_stations" ON "metro_stations".id =
"metro_stations_pcs".metro_station_id WHERE "pcs".id IN (469) ORDER
BY COALESCE(pcs.min_cost, pcs.max_cost) ASC
Look at WHERE clause. There is no additional params. Only IN operator. You can find more information if you will do EXPLAIN. I have run all tests and all is pretty well.
Thank. Here is a patch and I hope, that it will be useful.
No comments found
Create your profile
Help contribute to this project by taking a few moments to create your personal profile. Create your profile »
<h2 style="font-size: 14px">Tickets have moved to Github</h2>
The new ticket tracker is available at <a href="https://github.com/rails/rails/issues">https://github.com/rails/rails/issues</a>