Noticing a huge slowdown in a query with a ton of related tables in Zero.
The query is
return z.query.scenarios
.where("teamId", team.id)
.related("team", (q_team) => q_team.one())
.related("client", (q_client) => q_client.one())
.related("lender", (q_lender) => q_lender.one())
.related("loanPurpose", (q_loan_purpose) => q_loan_purpose.one())
.related("loanType", (q_loan_type) => q_loan_type.one())
.related("propertyType", (q_property_type) => q_property_type.one());./node_modules/.bin/dotenvx run -f .env.local -- npx analyze-query --schema-path='./lib/zero/schema.ts' --query='scenarios.where("teamId", 1).related("team", (q_team) => q_team.one()).related("client", (q_client) => q_client.one()).related("lender", (q_lender) => q_lender.one()).related("loanPurpose", (q_loan_purpose) => q_loan_purpose.one()).related("loanType", (q_loan_type) => q_loan_type.one()).related("propertyType", (q_property_type) => q_property_type.one())' --apply-permissions --auth-data='{"sub":"1", "lender_id": 1, "team_ids": [1]}'The results show this query is taking 1124.76ms
=== Query After Permissions: ===
scenarios
.where("team_id", 1)
.where("team_id", "IN", [1])
.related("team", (q) =>
q.where("1", "IS NOT", null).orderBy("id", "asc").limit(1),
)
.related("client", (q) =>
q.where("1", "IS NOT", null).orderBy("id", "asc").limit(1),
)
.related("lender", (q) =>
q.where("1", "IS NOT", null).orderBy("id", "asc").limit(1),
)
.related("loanPurpose", (q) =>
q.where("1", "IS NOT", null).orderBy("id", "asc").limit(1),
)
.related("loanType", (q) =>
q.where("1", "IS NOT", null).orderBy("id", "asc").limit(1),
)
.related("propertyType", (q) =>
q.where("1", "IS NOT", null).orderBy("id", "asc").limit(1),
)
.orderBy("id", "asc")=== Query Stats: ===
scenarios vended: { 'SELECT "id","public_id","down_payment_percentage","interest_rate","name","purchase_price","refinance","term","created_at","client_id","lender_id","loan_purpose_id","loan_type_id","property_type_id","team_id" FROM "scenarios" WHERE ("team_id" = ? AND "team_id" IN (SELECT value FROM json_each(?))) ORDER BY "id" asc': 2040 }
teams vended: { 'SELECT "id","public_id","name","avatar_url","organization_id" FROM "teams" WHERE "id" IS ? AND ? IS NOT ? ORDER BY "id" asc': 2040 }
clients vended: { 'SELECT "id","public_id","avatar_url","created_at","email_address","first_name","last_name","full_name","phone_number","team_id","user_id" FROM "clients" WHERE "id" IS ? AND ? IS NOT ? ORDER BY "id" asc': 2040 }
lenders vended: { 'SELECT "id","user_id" FROM "lenders" WHERE "id" IS ? AND ? IS NOT ? ORDER BY "id" asc': 2040 }
loan_purposes vended: { 'SELECT "id","name" FROM "loan_purposes" WHERE "id" IS ? AND ? IS NOT ? ORDER BY "id" asc': 2040 }
loan_types vended: { 'SELECT "id","name" FROM "loan_types" WHERE "id" IS ? AND ? IS NOT ? ORDER BY "id" asc': 2040 }
property_types vended: { 'SELECT "id","name" FROM "property_types" WHERE "id" IS ? AND ? IS NOT ? ORDER BY "id" asc': 2040 }
total rows considered: 14280 time: 1124.76ms ms
=== Query Plans: ===
query SELECT "id","public_id","down_payment_percentage","interest_rate","name","purchase_price","refinance","term","created_at","client_id","lender_id","loan_purpose_id","loan_type_id","property_type_id","team_id" FROM "scenarios" WHERE ("team_id" = ? AND "team_id" IN (SELECT value FROM json_each(?))) ORDER BY "id" asc
SEARCH scenarios USING INDEX index_scenarios_on_team_id (team_id=?)
LIST SUBQUERY 1
SCAN json_each VIRTUAL TABLE INDEX 1:
CREATE BLOOM FILTER
USE TEMP B-TREE FOR ORDER BYquery SELECT "id","public_id","name","avatar_url","organization_id" FROM "teams" WHERE "id" IS ? AND ? IS NOT ? ORDER BY "id" asc
SEARCH teams USING INDEX teams_pkey (id=?)query SELECT "id","public_id","avatar_url","created_at","email_address","first_name","last_name","full_name","phone_number","team_id","user_id" FROM "clients" WHERE "id" IS ? AND ? IS NOT ?
ORDER BY "id" asc
SEARCH clients
USING INDEX clients_pkey (id=?)query SELECT "id","user_id" FROM "lenders" WHERE "id" IS ? AND ? IS NOT ? ORDER BY "id" asc
SEARCH lenders USING INDEX lenders_pkey (id=?)query SELECT "id","name" FROM "loan_purposes" WHERE "id" IS ? AND ? IS NOT ? ORDER BY "id" asc
SEARCH loan_purposes USING INDEX loan_purposes_pkey (id=?)query SELECT "id","name" FROM "loan_types" WHERE "id" IS ? AND ? IS NOT ? ORDER BY "id" asc
SEARCH loan_types USING INDEX loan_types_pkey (id=?)query SELECT "id","name" FROM "property_types" WHERE "id" IS ? AND ? IS NOT ? ORDER BY "id" asc
SEARCH property_types USING INDEX property_types_pkey (id=?)In ActiveRecord we can do Scenario.where(team_id: 1).preload(:loan_type, :loan_purpose, :property_type, :lender, :client, :team).explain.
Using preload tells ActiveRecord to issue separate queries to all the associated tables to gather the data, rather than
attempting to create a bunch of joins/subqueries.
The results summed up are about 125ms
Scenario Load (114.9ms) SELECT "scenarios".* FROM "scenarios" WHERE "scenarios"."team_id" = 1 /*application='LendingSheetsBackend'*/
LoanType Load (0.6ms) SELECT "loan_types".* FROM "loan_types" WHERE "loan_types"."id" IN (1, 2, 3, 4, 5, 6, 7, 8, 9) /*application='LendingSheetsBackend'*/
LoanPurpose Load (0.4ms) SELECT "loan_purposes".* FROM "loan_purposes" WHERE "loan_purposes"."id" IN (1, 2, 3, 4, 5, 6) /*application='LendingSheetsBackend'*/
PropertyType Load (0.5ms) SELECT "property_types".* FROM "property_types" WHERE "property_types"."id" IN (1, 2, 3, 4, 5, 6, 7) /*application='LendingSheetsBackend'*/
Lender Load (0.5ms) SELECT "lenders".* FROM "lenders" WHERE "lenders"."id" IN (1, 3) /*application='LendingSheetsBackend'*/
Client Load (7.3ms) SELECT "clients".* FROM "clients" WHERE "clients"."id" IN (7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108) /*application='LendingSheetsBackend'*/
Team Load (0.4ms) SELECT "teams".* FROM "teams" WHERE "teams"."id" = 1 /*application='LendingSheetsBackend'*/And all the query plans
EXPLAIN SELECT "scenarios".* FROM "scenarios" WHERE "scenarios"."team_id" = 1 /*application='LendingSheetsBackend'*/
QUERY PLAN
---------------------------------------------------------------------------------------------------
Index Scan using index_scenarios_on_team_id on scenarios (cost=0.28..100.94 rows=2038 width=137)
Index Cond: (team_id = 1)
(2 rows)EXPLAIN SELECT "loan_types".* FROM "loan_types" WHERE "loan_types"."id" IN (1, 2, 3, 4, 5, 6, 7, 8, 9) /*application='LendingSheetsBackend'*/
QUERY PLAN
-----------------------------------------------------------
Seq Scan on loan_types (cost=0.02..1.16 rows=6 width=88)
Filter: (id = ANY ('{1,2,3,4,5,6,7,8,9}'::bigint[]))
(2 rows)EXPLAIN SELECT "loan_purposes".* FROM "loan_purposes" WHERE "loan_purposes"."id" IN (1, 2, 3, 4, 5, 6) /*application='LendingSheetsBackend'*/
QUERY PLAN
--------------------------------------------------------------
Seq Scan on loan_purposes (cost=0.00..1.10 rows=6 width=56)
Filter: (id = ANY ('{1,2,3,4,5,6}'::bigint[]))
(2 rows)EXPLAIN SELECT "property_types".* FROM "property_types" WHERE "property_types"."id" IN (1, 2, 3, 4, 5, 6, 7) /*application='LendingSheetsBackend'*/
QUERY PLAN
---------------------------------------------------------------
Seq Scan on property_types (cost=0.00..1.13 rows=7 width=56)
Filter: (id = ANY ('{1,2,3,4,5,6,7}'::bigint[]))
(2 rows)EXPLAIN SELECT "lenders".* FROM "lenders" WHERE "lenders"."id" IN (1, 3) /*application='LendingSheetsBackend'*/ QUERY PLAN
--------------------------------------------------------
Seq Scan on lenders (cost=0.00..1.04 rows=2 width=32)
Filter: (id = ANY ('{1,3}'::bigint[]))
(2 rows) EXPLAIN SELECT "clients".* FROM "clients" WHERE "clients"."id" IN (7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108) /*application='LendingSheetsBackend'*/
Seq Scan on clients (cost=0.26..4.88 rows=102 width=182)
Filter: (id = ANY ('{7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108}'::bigint[]))
(2 rows)EXPLAIN SELECT "scenarios".* FROM "scenarios" WHERE "scenarios"."team_id" = 1 /*application='LendingSheetsBackend'*/
QUERY PLAN
---------------------------------------------------------------------------------------------------
Index Scan using index_scenarios_on_team_id on scenarios (cost=0.28..100.94 rows=2038 width=137)
Index Cond: (team_id = 1)
(2 rows)EXPLAIN SELECT "loan_types".* FROM "loan_types" WHERE "loan_types"."id" IN (1, 2, 3, 4, 5, 6, 7, 8, 9) /*application='LendingSheetsBackend'*/
QUERY PLAN
-----------------------------------------------------------
Seq Scan on loan_types (cost=0.02..1.16 rows=6 width=88)
Filter: (id = ANY ('{1,2,3,4,5,6,7,8,9}'::bigint[]))
(2 rows)EXPLAIN SELECT "loan_purposes".* FROM "loan_purposes" WHERE "loan_purposes"."id" IN (1, 2, 3, 4, 5, 6) /*application='LendingSheetsBackend'*/
QUERY PLAN
--------------------------------------------------------------
Seq Scan on loan_purposes (cost=0.00..1.10 rows=6 width=56)
Filter: (id = ANY ('{1,2,3,4,5,6}'::bigint[]))
(2 rows)EXPLAIN SELECT "property_types".* FROM "property_types" WHERE "property_types"."id" IN (1, 2, 3, 4, 5, 6, 7) /*application='LendingSheetsBackend'*/
QUERY PLAN
---------------------------------------------------------------
Seq Scan on property_types (cost=0.00..1.13 rows=7 width=56)
Filter: (id = ANY ('{1,2,3,4,5,6,7}'::bigint[]))
(2 rows)EXPLAIN SELECT "lenders".* FROM "lenders" WHERE "lenders"."id" IN (1, 3) /*application='LendingSheetsBackend'*/
QUERY PLAN
--------------------------------------------------------
Seq Scan on lenders (cost=0.00..1.04 rows=2 width=32)
Filter: (id = ANY ('{1,3}'::bigint[]))
(2 rows)EXPLAIN SELECT "teams".* FROM "teams" WHERE "teams"."id" = 1 /*application='LendingSheetsBackend'*/
QUERY PLAN
-------------------------------------------------------
Seq Scan on teams (cost=0.00..1.02 rows=1 width=138)
Filter: (id = 1)
(2 rows)
Scenario.where(team_id: 1).eager_load(:loan_type, :loan_purpose, :property_type, :lender, :client, :team).explain
SQL (235.2ms) SELECT "scenarios"."id" AS t0_r0, "scenarios"."team_id" AS t0_r1, "scenarios"."client_id" AS t0_r2, "scenarios"."lender_id" AS t0_r3, "scenarios"."loan_type_id" AS t0_r4, "scenarios"."property_type_id" AS t0_r5, "scenarios"."loan_purpose_id" AS t0_r6, "scenarios"."name" AS t0_r7, "scenarios"."purchase_price" AS t0_r8, "scenarios"."down_payment_percentage" AS t0_r9, "scenarios"."interest_rate" AS t0_r10, "scenarios"."term" AS t0_r11, "scenarios"."refinance" AS t0_r12, "scenarios"."public_id" AS t0_r13, "scenarios"."created_at" AS t0_r14, "scenarios"."updated_at" AS t0_r15, "loan_types"."id" AS t1_r0, "loan_types"."name" AS t1_r1, "loan_types"."short_name" AS t1_r2, "loan_types"."created_at" AS t1_r3, "loan_types"."updated_at" AS t1_r4, "loan_purposes"."id" AS t2_r0, "loan_purposes"."name" AS t2_r1, "loan_purposes"."created_at" AS t2_r2, "loan_purposes"."updated_at" AS t2_r3, "property_types"."id" AS t3_r0, "property_types"."name" AS t3_r1, "property_types"."created_at" AS t3_r2, "property_types"."updated_at" AS t3_r3, "lenders"."id" AS t4_r0, "lenders"."user_id" AS t4_r1, "lenders"."created_at" AS t4_r2, "lenders"."updated_at" AS t4_r3, "clients"."id" AS t5_r0, "clients"."user_id" AS t5_r1, "clients"."team_id" AS t5_r2, "clients"."first_name" AS t5_r3, "clients"."last_name" AS t5_r4, "clients"."email_address" AS t5_r5, "clients"."avatar_url" AS t5_r6, "clients"."created_at" AS t5_r7, "clients"."updated_at" AS t5_r8, "clients"."phone_number" AS t5_r9, "clients"."public_id" AS t5_r10, "clients"."full_name" AS t5_r11, "teams"."id" AS t6_r0, "teams"."name" AS t6_r1, "teams"."avatar_url" AS t6_r2, "teams"."organization_id" AS t6_r3, "teams"."created_at" AS t6_r4, "teams"."updated_at" AS t6_r5, "teams"."public_id" AS t6_r6 FROM "scenarios" LEFT OUTER JOIN "loan_types" ON "loan_types"."id" = "scenarios"."loan_type_id" LEFT OUTER JOIN "loan_purposes" ON "loan_purposes"."id" = "scenarios"."loan_purpose_id" LEFT OUTER JOIN "property_types" ON "property_types"."id" = "scenarios"."property_type_id" LEFT OUTER JOIN "lenders" ON "lenders"."id" = "scenarios"."lender_id" LEFT OUTER JOIN "clients" ON "clients"."id" = "scenarios"."client_id" LEFT OUTER JOIN "teams" ON "teams"."id" = "scenarios"."team_id" WHERE "scenarios"."team_id" = 1 /application='LendingSheetsBackend'/ => EXPLAIN SELECT "scenarios"."id" AS t0_r0, "scenarios"."team_id" AS t0_r1, "scenarios"."client_id" AS t0_r2, "scenarios"."lender_id" AS t0_r3, "scenarios"."loan_type_id" AS t0_r4, "scenarios"."property_type_id" AS t0_r5, "scenarios"."loan_purpose_id" AS t0_r6, "scenarios"."name" AS t0_r7, "scenarios"."purchase_price" AS t0_r8, "scenarios"."down_payment_percentage" AS t0_r9, "scenarios"."interest_rate" AS t0_r10, "scenarios"."term" AS t0_r11, "scenarios"."refinance" AS t0_r12, "scenarios"."public_id" AS t0_r13, "scenarios"."created_at" AS t0_r14, "scenarios"."updated_at" AS t0_r15, "loan_types"."id" AS t1_r0, "loan_types"."name" AS t1_r1, "loan_types"."short_name" AS t1_r2, "loan_types"."created_at" AS t1_r3, "loan_types"."updated_at" AS t1_r4, "loan_purposes"."id" AS t2_r0, "loan_purposes"."name" AS t2_r1, "loan_purposes"."created_at" AS t2_r2, "loan_purposes"."updated_at" AS t2_r3, "property_types"."id" AS t3_r0, "property_types"."name" AS t3_r1, "property_types"."created_at" AS t3_r2, "property_types"."updated_at" AS t3_r3, "lenders"."id" AS t4_r0, "lenders"."user_id" AS t4_r1, "lenders"."created_at" AS t4_r2, "lenders"."updated_at" AS t4_r3, "clients"."id" AS t5_r0, "clients"."user_id" AS t5_r1, "clients"."team_id" AS t5_r2, "clients"."first_name" AS t5_r3, "clients"."last_name" AS t5_r4, "clients"."email_address" AS t5_r5, "clients"."avatar_url" AS t5_r6, "clients"."created_at" AS t5_r7, "clients"."updated_at" AS t5_r8, "clients"."phone_number" AS t5_r9, "clients"."public_id" AS t5_r10, "clients"."full_name" AS t5_r11, "teams"."id" AS t6_r0, "teams"."name" AS t6_r1, "teams"."avatar_url" AS t6_r2, "teams"."organization_id" AS t6_r3, "teams"."created_at" AS t6_r4, "teams"."updated_at" AS t6_r5, "teams"."public_id" AS t6_r6 FROM "scenarios" LEFT OUTER JOIN "loan_types" ON "loan_types"."id" = "scenarios"."loan_type_id" LEFT OUTER JOIN "loan_purposes" ON "loan_purposes"."id" = "scenarios"."loan_purpose_id" LEFT OUTER JOIN "property_types" ON "property_types"."id" = "scenarios"."property_type_id" LEFT OUTER JOIN "lenders" ON "lenders"."id" = "scenarios"."lender_id" LEFT OUTER JOIN "clients" ON "clients"."id" = "scenarios"."client_id" LEFT OUTER JOIN "teams" ON "teams"."id" = "scenarios"."team_id" WHERE "scenarios"."team_id" = 1 /application='LendingSheetsBackend'/ QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------- Nested Loop Left Join (cost=10.27..181.49 rows=2038 width=689) -> Hash Left Join (cost=10.27..154.99 rows=2038 width=551) Hash Cond: (scenarios.client_id = clients.id) -> Hash Left Join (cost=4.84..143.99 rows=2038 width=369) Hash Cond: (scenarios.lender_id = lenders.id) -> Hash Left Join (cost=3.78..130.02 rows=2038 width=337) Hash Cond: (scenarios.property_type_id = property_types.id) -> Hash Left Join (cost=2.62..120.28 rows=2038 width=281)
Hash Cond: (scenarios.loan_purpose_id = loan_purposes.id)
-> Hash Left Join (cost=1.48..110.01 rows=2038 width=225)
Hash Cond: (scenarios.loan_type_id = loan_types.id) -> Index Scan using index_scenarios_on_team_id on scenarios (cost=0.28..100.94 rows=2038 width=137)
Index Cond: (team_id = 1)
-> Hash (cost=1.09..1.09 rows=9 width=88)
-> Seq Scan on loan_types (cost=0.00..1.09 rows=9 width=88)
-> Hash (cost=1.06..1.06 rows=6 width=56)
-> Seq Scan on loan_purposes (cost=0.00..1.06 rows=6 width=56)
-> Hash (cost=1.07..1.07 rows=7 width=56) -> Seq Scan on property_types (cost=0.00..1.07 rows=7 width=56)
-> Hash (cost=1.03..1.03 rows=3 width=32)
-> Seq Scan on lenders (cost=0.00..1.03 rows=3 width=32)
-> Hash (cost=4.08..4.08 rows=108 width=182)
Preparing full inspection value...
=>
EXPLAIN SELECT "scenarios"."id" AS t0_r0, "scenarios"."team_id" AS t0_r1, "scenarios"."client_id" AS t0_r2, "scenarios"."lender_id" AS t0_r3, "scenarios"."loan_type_id" AS t0_r4, "scenarios"."property_type_id" AS t0_r5, "scenarios"."loan_purpose_id" AS t0_r6, "scenarios"."name" AS t0_r7, "scenarios"."purchase_price" AS t0_r8, "scenarios"."down_payment_percentage" AS t0_r9, "scenarios"."interest_rate" AS t0_r10, "scenarios"."term" AS t0_r11, "scenarios"."refinance" AS t0_r12, "scenarios"."public_id" AS t0_r13, "scenarios"."created_at" AS t0_r14, "scenarios"."updated_at" AS t0_r15, "loan_types"."id" AS t1_r0, "loan_types"."name" AS t1_r1, "loan_types"."short_name" AS t1_r2, "loan_types"."created_at" AS t1_r3, "loan_types"."updated_at" AS t1_r4, "loan_purposes"."id" AS t2_r0, "loan_purposes"."name" AS t2_r1, "loan_purposes"."created_at" AS t2_r2, "loan_purposes"."updated_at" AS t2_r3, "property_types"."id" AS t3_r0, "property_types"."name" AS t3_r1, "property_types"."created_at" AS t3_r2, "property_types"."updated_at" AS t3_r3, "lenders"."id" AS t4_r0, "lenders"."user_id" AS t4_r1, "lenders"."created_at" AS t4_r2, "lenders"."updated_at" AS t4_r3, "clients"."id" AS t5_r0, "clients"."user_id" AS t5_r1, "clients"."team_id" AS t5_r2, "clients"."first_name" AS t5_r3, "clients"."last_name" AS t5_r4, "clients"."email_address" AS t5_r5, "clients"."avatar_url" AS t5_r6, "clients"."created_at" AS t5_r7, "clients"."updated_at" AS t5_r8, "clients"."phone_number" AS t5_r9, "clients"."public_id" AS t5_r10, "clients"."full_name" AS t5_r11, "teams"."id" AS t6_r0, "teams"."name" AS t6_r1, "teams"."avatar_url" AS t6_r2, "teams"."organization_id" AS t6_r3, "teams"."created_at" AS t6_r4, "teams"."updated_at" AS t6_r5, "teams"."public_id" AS t6_r6 FROM "scenarios" LEFT OUTER JOIN "loan_types" ON "loan_types"."id" = "scenarios"."loan_type_id" LEFT OUTER JOIN "loan_purposes" ON "loan_purposes"."id" = "scenarios"."loan_purpose_id" LEFT OUTER JOIN "property_types" ON "property_types"."id" = "scenarios"."property_type_id" LEFT OUTER JOIN "lenders" ON "lenders"."id" = "scenarios"."lender_id" LEFT OUTER JOIN "clients" ON "clients"."id" = "scenarios"."client_id" LEFT OUTER JOIN "teams" ON "teams"."id" = "scenarios"."team_id" WHERE "scenarios"."team_id" = 1 /application='LendingSheetsBackend'/ QUERY PLAN
Nested Loop Left Join (cost=10.27..181.49 rows=2038 width=689)
-> Hash Left Join (cost=10.27..154.99 rows=2038 width=551)
Hash Cond: (scenarios.client_id = clients.id)
-> Hash Left Join (cost=4.84..143.99 rows=2038 width=369)
Hash Cond: (scenarios.lender_id = lenders.id) -> Hash Left Join (cost=3.78..130.02 rows=2038 width=337)
Hash Cond: (scenarios.property_type_id = property_types.id)
-> Hash Left Join (cost=2.62..120.28 rows=2038 width=281)
Hash Cond: (scenarios.loan_purpose_id = loan_purposes.id)
-> Hash Left Join (cost=1.48..110.01 rows=2038 width=225)
Hash Cond: (scenarios.loan_type_id = loan_types.id)
-> Index Scan using index_scenarios_on_team_id on scenarios (cost=0.28..100.94 rows=2038 width=137) Index Cond: (team_id = 1)
-> Hash (cost=1.09..1.09 rows=9 width=88)
-> Seq Scan on loan_types (cost=0.00..1.09 rows=9 width=88)
-> Hash (cost=1.06..1.06 rows=6 width=56)
-> Seq Scan on loan_purposes (cost=0.00..1.06 rows=6 width=56)
-> Hash (cost=1.07..1.07 rows=7 width=56)
-> Seq Scan on property_types (cost=0.00..1.07 rows=7 width=56) -> Hash (cost=1.03..1.03 rows=3 width=32)
-> Seq Scan on lenders (cost=0.00..1.03 rows=3 width=32)
-> Hash (cost=4.08..4.08 rows=108 width=182)
-> Seq Scan on clients (cost=0.00..4.08 rows=108 width=182)
-> Materialize (cost=0.00..1.03 rows=1 width=138)
-> Seq Scan on teams (cost=0.00..1.02 rows=1 width=138)
Filter: (id = 1)
(26 rows)