EG 2.1
Pg 9.0
If you have many barcodes that are all numerals and start with a certain sequence, a query from the patron search form can result in a very bad plan, such as:
explain SELECT evergreen.lowercase(CAST(users.family_name AS text)), evergreen.lowercase(CAST(users.first_given_name AS text)), evergreen.lowercase(CAST(users.id AS text))
FROM actor.usr AS users JOIN (SELECT DISTINCT usr FROM actor.card WHERE evergreen.lowercase(barcode) LIKE '21307'||'%') AS card ON (card.usr = users.id)
JOIN actor.org_unit_descendants(10, 0) d ON (d.id = users.home_ou)
JOIN (SELECT id as id FROM actor.usr u WHERE evergreen.lowercase(CAST(profile AS text)) ~ '^') AS search ON (search.id = users.id)
WHERE users.deleted = FALSE
GROUP BY evergreen.lowercase(CAST(users.family_name AS text)), evergreen.lowercase(CAST(users.first_given_name AS text)), evergreen.lowercase(CAST(users.id AS text))
ORDER BY evergreen.lowercase(CAST(users.family_name AS text)) , evergreen.lowercase(CAST(users.first_given_name AS text)) , evergreen.lowercase(CAST(users.id AS text))
LIMIT 51;
QUERY PLAN
-----------------------------------------------------------------------------------------------------------------------------------------------------------------
Limit (cost=-23493470903261368.00..-23493470903261368.00 rows=51 width=17)
-> Sort (cost=-23493470903261368.00..-23493470903261360.00 rows=2801 width=17)
Sort Key: (lowercase(users.family_name)), (lowercase(users.first_given_name)), (lowercase((users.id)::text))
-> HashAggregate (cost=-23493470903263604.00..-23493470903261460.00 rows=2801 width=17)
-> Merge Join (cost=-23493470903266188.00..-23493470903263624.00 rows=2801 width=17)
Merge Cond: (users.home_ou = d.id)
-> Sort (cost=-23493470903266188.00..-23493470903265984.00 rows=81232 width=21)
Sort Key: users.home_ou
-> Nested Loop (cost=-28783.12..-23493470903272812.00 rows=81232 width=21)
Join Filter: (actor.card.usr = u.id)
-> Seq Scan on usr u (cost=0.00..262462.50 rows=951148 width=4)
Filter: (lowercase((profile)::text) ~ '^'::text)
-> Nested Loop (cost=-28783.12..-24700122241.05 rows=81232 width=25)
Join Filter: (users.id = actor.card.usr)
-> Seq Scan on usr users (cost=0.00..17517.43 rows=944806 width=21)
Filter: (NOT deleted)
-> HashAggregate (cost=-28783.12..-27970.80 rows=81232 width=4)
-> Index Scan using actor_card_barcode_evergreen_lowercase_idx on card (cost=0.50..-29305.58 rows=208984 width=4)
Index Cond: ((lowercase(barcode) >= '21307'::text) AND (lowercase(barcode) < '21308'::text))
Filter: (lowercase(barcode) ~~ '21307%'::text)
-> Materialize (cost=0.27..0.28 rows=1 width=4)
-> Sort (cost=0.27..0.28 rows=1 width=4)
Sort Key: d.id
-> Function Scan on org_unit_descendants d (cost=0.25..0.26 rows=1 width=4)
The client throws a network error and continues, but you have a runaway query in the database.
Removing the lowercase(barcode) function does much better:
explain SELECT evergreen.lowercase(CAST(users.family_name AS text)), evergreen.lowercase(CAST(users.first_given_name AS text)), evergreen.lowercase(CAST(users.id AS text))
FROM actor.usr AS users JOIN (SELECT DISTINCT usr FROM actor.card WHERE barcode LIKE '21307'||'%') AS card ON (card.usr = users.id)
JOIN actor.org_unit_descendants(10, 0) d ON (d.id = users.home_ou)
JOIN (SELECT id as id FROM actor.usr u WHERE evergreen.lowercase(CAST(profile AS text)) ~ '^') AS search ON (search.id = users.id)
WHERE users.deleted = FALSE
GROUP BY evergreen.lowercase(CAST(users.family_name AS text)), evergreen.lowercase(CAST(users.first_given_name AS text)), evergreen.lowercase(CAST(users.id AS text))
ORDER BY evergreen.lowercase(CAST(users.family_name AS text)) , evergreen.lowercase(CAST(users.first_given_name AS text)) , evergreen.lowercase(CAST(users.id AS text))
LIMIT 51;
QUERY PLAN
------------------------------------------------------------------------------------------------------------------------------------
Limit (cost=28822.83..28822.96 rows=51 width=17)
-> Sort (cost=28822.83..28829.84 rows=2801 width=17)
Sort Key: (lowercase(users.family_name)), (lowercase(users.first_given_name)), (lowercase((users.id)::text))
-> HashAggregate (cost=26586.62..28729.39 rows=2801 width=17)
-> Nested Loop (cost=19721.73..26565.61 rows=2801 width=17)
-> Hash Join (cost=19721.73..21679.00 rows=2801 width=21)
Hash Cond: (actor.card.usr = users.id)
-> HashAggregate (cost=10224.77..11037.09 rows=81232 width=4)
-> Bitmap Heap Scan on card (cost=2831.57..9702.31 rows=208984 width=4)
Filter: (barcode ~~ '21307%'::text)
-> Bitmap Index Scan on card_barcode_key (cost=0.00..2779.32 rows=201499 width=0)
Index Cond: ((barcode >= '21307'::text) AND (barcode < '21308'::text))
-> Hash (cost=9089.71..9089.71 rows=32580 width=17)
-> Nested Loop (cost=346.68..9089.71 rows=32580 width=17)
-> Function Scan on org_unit_descendants d (cost=0.25..0.26 rows=1 width=4)
-> Bitmap Heap Scan on usr users (cost=346.43..8679.44 rows=32801 width=21)
Recheck Cond: (users.home_ou = d.id)
Filter: (NOT users.deleted)
-> Bitmap Index Scan on actor_usr_home_ou_idx (cost=0.00..338.28 rows=32801 width=0)
Index Cond: (users.home_ou = d.id)
-> Index Scan using usr_pkey on usr u (cost=0.00..0.98 rows=1 width=4)
Index Cond: (u.id = actor.card.usr)
Filter: (lowercase((u.profile)::text) ~ '^'::text)
Patch against master attached.
Branchified:
For sharing lp874603 via the remote repo working:
You need only add the remote once, regardless of how many branches you wish to look at. evergreen- ils.org/ working/ Evergreen :working/ Evergreen
To add this repo as working:
Read-only (git protocol):
git remote add working git://git.
Read-write (ssh protocol):
git remote add working <email address hidden>
Once you have the remote added you can check out this branch: collab/ dyrcona/ lp874603
git checkout -b lp874603 working/
For sharing lp874603_2_1 via the remote repo working:
You need only add the remote once, regardless of how many branches you wish to look at. evergreen- ils.org/ working/ Evergreen :working/ Evergreen
To add this repo as working:
Read-only (git protocol):
git remote add working git://git.
Read-write (ssh protocol):
git remote add working <email address hidden>
Once you have the remote added you can check out this branch: collab/ dyrcona/ lp874603_ 2_1
git checkout -b lp874603_2_1 working/
Not tested, and therefore not signed off, yet.