I found one of our APIs using this query in our materialised view which generates aggregated report on asset inventory (PostgreSQL 13.3) and is very slow on a table with 1.2 million rows
SELECT COALESCE (SUM(CASE
WHEN (t1.mech_id = 222 OR t1.workshop_representation_id = 222)
AND t1.is_incoming = true
THEN 1
ELSE 0
END), 0) as point1,
COALESCE(SUM(CASE
WHEN (t1.mech_id = 222 OR t1.workshop_representation_id = 222)
AND t1.is_incoming = false
AND t1.train_id NOT IN (
SELECT distinct t1.train_id
FROM mvw_engine_details x1
WHERE x1.inspection_date BETWEEN '2022-03-01' AND '2022-06-05'
AND (x1.mech_id = 222 OR x1.workshop_representation_id = 222) AND x1.is_incoming = true
)
THEN 1
ELSE 0
END), 0) as point2,
COALESCE(SUM(CASE
WHEN (t1.mech_id = 222 OR t1.workshop_representation_id = 222)
AND t1.is_incoming = true
AND t1.express_train = 'true'
THEN 1
ELSE 0
END), 0) as point1express,
COALESCE(SUM(CASE
WHEN (t1.mech_id = 222 OR t1.workshop_representation_id = 222)
AND t1.is_incoming = false
AND t1.train_id NOT IN (
SELECT distinct t1.train_id
FROM mvw_engine_details x1
WHERE x1.inspection_date BETWEEN '2022-03-01' AND '2022-06-05'
AND (x1.mech_id = 222 OR x1.workshop_representation_id = 222) AND x1.is_incoming = true
)
AND t1.express_train = 'true'
THEN 1
ELSE 0
END), 0) as point2express
FROM mvw_engine_details t1
WHERE t1.inspection_date BETWEEN '2022-03-01' AND '2022-06-05'
After creating some index here are the current explain analyse stats:
Planning Time: 0.323 ms
Execution Time: 6.380 ms
CREATE INDEX IF NOT EXISTS mvw_transport_train_id_inspection_date
ON datamart.mvw_engine_details(inspection_date, train_id);
CREATE INDEX IF NOT EXISTS mvw_transport_inspection_date_idx
ON datamart.mvw_engine_details (inspection_date)
WITH (deduplicate_items = off);
CREATE INDEX IF NOT EXISTS mvw_transport_train_id_idx
ON datamart.mvw_engine_details (train_id)
WITH (deduplicate_items = off);
Is there any way to improve the query? or is it badly constructed?
