PostgreSQL: Performance: ORDER BY an indexed column is slowing down the query performance 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 -&gt;&gt; '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 -&gt; 'chain'::text) -&gt;&gt; 'name'::text)));
CREATE INDEX idx_theatres_city_name ON public.theatres USING btree (((((data -&gt; 'address'::text) -&gt; 'city'::text) -&gt;&gt; 'name'::text)));
CREATE INDEX idx_theatres_country_name ON public.theatres USING btree (((((data -&gt; 'address'::text) -&gt; 'country'::text) -&gt;&gt; '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 -&gt; 'address'::text) -&gt; 'province'::text) -&gt;&gt; '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.
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.