Question

SELECT s.id, s.name, s.updated_at, COUNT(*) OVER ()
FROM screens s
INNER JOIN theatres t ON s.theatre_id = t.id 
LEFT JOIN company_screen_mappings AS csm ON csm.screen_id = s.id AND csm.is_deleted = FALSE AND csm.company_id = 'f5003aa3-3621-498a-ab0f-526706fda88f'
WHERE 1=1 ORDER BY s.name asc  LIMIT 50 OFFSET 0

Here is the query plan: https://explain.depesz.com/s/UC9B

Here are the indexes in the associated tables

CREATE INDEX idx_screens_name ON public.screens USING btree (name);
CREATE INDEX idx_screens_number ON public.screens USING btree (((data ->> 'number'::text)));
CREATE INDEX idx_screens_tags ON public.screens USING gin (tags);
CREATE INDEX idx_screens_theatre_id ON public.screens USING btree (theatre_id);

CREATE INDEX idx_theatre_companies ON public.theatres USING gin (company_ids);
CREATE INDEX idx_theatres_chain_name ON public.theatres USING btree ((((data -> 'chain'::text) ->> 'name'::text)));
CREATE INDEX idx_theatres_city_name ON public.theatres USING btree (((((data -> 'address'::text) -> 'city'::text) ->> 'name'::text)));
CREATE INDEX idx_theatres_country_name ON public.theatres USING btree (((((data -> 'address'::text) -> 'country'::text) ->> 'name'::text)));
CREATE INDEX idx_theatres_name ON public.theatres USING btree (name);
CREATE INDEX idx_theatres_province_name ON public.theatres USING btree (((((data -> 'address'::text) -> 'province'::text) ->> 'name'::text)));
CREATE INDEX idx_theatres_qwc_is_active ON public.theatres USING btree (qwc_is_active);
CREATE INDEX idx_theatres_tags ON public.theatres USING gin (tags);

CREATE UNIQUE INDEX company_screen_mappings_key ON public.company_screen_mappings USING btree (company_id, screen_id) WHERE (is_deleted = false);

The moment I remove ORDER BY s.name the query is considerably fast. However, s.name is indexed, why is this happening? Is there a way I could optimize the query? Please suggest.

I need the result ordered by name. I could notice that removing COUNT(*) OVER() greatly improves the query execution time. But I need the COUNT as well.

Was it helpful?

Solution

It is normal that retrieving a sorted result is more effort.

If you want the total count, all rows have to be scanned, even if you only return the first 50.

You could try order by name || '' to see if a sort would be faster.

My recommendation is not to retrieve the total count together with the query.

The optimizer's estimates are good in this case, so you should use an approximate result count by running

EXPLAIN (FORMAT JSON) SELECT ...

and retrieving the Plan Rows.

Licensed under: CC-BY-SA with attribution
Not affiliated with dba.stackexchange
scroll top