Abstrct / Schemaverse

The Schemaverse is a space-based strategy game implemented entirely within a PostgreSQL database. Compete against other players using raw SQL commands to command your fleet. Or, if your PL/pgSQL-foo is strong, wield it to write AI and have your fleet command itself!

Home Page:schemaverse.com

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

my_ships view inducing Seq Scans on underlying tables

cbbrowne opened this issue · comments

I have been finding queries against my_ships to be extremely slow.

An EXPLAIN shows why, pretty clearly:
schemaverse@db.schemaverse.com-> explain select * from my_ships;

QUERY PLAN

Hash Join (cost=12653.52..13744.93 rows=2070 width=189)
Hash Cond: (ship_control.ship_id = ship.id)
-> Seq Scan on ship_control (cost=0.00..882.14 rows=37714 width=83)
-> Hash (cost=12627.57..12627.57 rows=2076 width=110)
-> Seq Scan on ship (cost=0.00..12627.57 rows=2076 width=110)
Filter: ((NOT destroyed) AND (player_id = get_player_id("session_user"())))
(6 rows)

None of the indexes are doing any good; it's doing Seq Scans across both tables.

Here is a fix:
cbbrowne@ebb1d6c

This does the following:
a) Adds player_id to ship_control, so that becomes indexable
b) Adds an index on that
c) Adds a partial index on ship(player_id) with condition "where not destroyed"

Equivalent query plans:

schemaverse@[local]-> explain select * from my_ships;

QUERY PLAN

Nested Loop (cost=4.26..107.91 rows=1 width=178)
-> Bitmap Heap Scan on ship (cost=4.26..91.11 rows=1 width=104)
Recheck Cond: (NOT destroyed)
Filter: (player_id = get_player_id("session_user"()))
-> Bitmap Index Scan on live_peoples_ships (cost=0.00..4.26 rows=290 width=0)
-> Index Scan using ship_control_pkey on ship_control (cost=0.00..8.52 rows=1 width=78)
Index Cond: (ship_id = ship.id)
Filter: (player_id = get_player_id("session_user"()))
SubPlan 1
-> Index Scan using ship_health_pkey on ship_health sh (cost=0.00..8.27 rows=1 width=4)
Index Cond: (ship_id = ship.id)
(11 rows)

Actually, the partial index is probably enough to get the big gains.

schemaverse@[local]-> explain select * from my_ships;

QUERY PLAN

Nested Loop (cost=4.26..107.66 rows=1 width=178)
-> Bitmap Heap Scan on ship (cost=4.26..91.11 rows=1 width=104)
Recheck Cond: (NOT destroyed)
Filter: (player_id = get_player_id("session_user"()))
-> Bitmap Index Scan on live_peoples_ships (cost=0.00..4.26 rows=290 width=0)
-> Index Scan using ship_control_pkey on ship_control (cost=0.00..8.27 rows=1 width=78)
Index Cond: (ship_id = ship.id)
SubPlan 1
-> Index Scan using ship_health_pkey on ship_health sh (cost=0.00..8.27 rows=1 width=4)
Index Cond: (ship_id = ship.id)
(10 rows)

That's inducing much the same plan without the extra player_id column on ship_control.

cbbrowne@a610be6

By the way, adding the partial index into the live copy would be a not-invasive change, and I expect it would massively improve performance.