From: | Nicolas Lutic <n(dot)lutic(at)loxodata(dot)com> |
---|---|
To: | pgsql-hackers(at)lists(dot)postgresql(dot)org |
Subject: | planner chooses incremental but not the best one |
Date: | 2023-12-12 08:40:14 |
Message-ID: | d2f06ddc-a8d4-48ea-893b-a95255c632b9@loxodata.com |
Views: | Raw Message | Whole Thread | Download mbox | Resend email |
Thread: | |
Lists: | pgsql-hackers |
Dear Hackers,
I've come across a behaviour of the planner I can't explain.
After a migration from 11 to 15 (on RDS) we noticed a degradation in
response time on a query, it went from a few seconds to ten minutes.
A vacuum(analyze) has been realized to be sure that all is clean.
The 'explain analyze' shows us a change of plan. Postgresql 15 chooses
`incremental sort` with an index corresponding to the ORDER BY clause
(on the created_at column). The previous v11 plan used a more efficient
index.
By deactivating incremental sort, response times in v15 are equal to v11
one.
Here is the query
SELECT inputdocum0_.id AS col_0_0_
FROM document_management_services.input_document inputdocum0_
WHERE (inputdocum0_.indexation_domain_id in
('2d29daf6-e151-479a-a52a-78b08bb3009d'))
AND (inputdocum0_.indexation_subsidiary_id in
('9f9df402-f70b-40d9-b283-a3c35232469a'))
AND (inputdocum0_.locked_at IS NULL)
AND (inputdocum0_.locked_by_app IS NULL)
AND (inputdocum0_.locked_by_user IS NULL)
AND (inputdocum0_.lock_time_out IS NULL)
AND inputdocum0_.archiving_state<> 'DESTROYED'
AND (inputdocum0_.creation_state in ('READY'))
AND inputdocum0_.active_content=true
AND (inputdocum0_.processing_state in ('PENDING_INDEXATION'))
ORDER BY inputdocum0_.created_at ASC,
inputdocum0_.reception_id ASC,
inputdocum0_.reception_order ASC
LIMIT 50 ;
Here are some details, the table `input_document` is partionned by hash
with 20 partitions with a lot of indexes
Indexes:
"input_document_pkey" PRIMARY KEY, btree (id)
"input_document_api_version_idx" btree (api_version) INVALID
"input_document_created_at_idx" btree (created_at)
"input_document_created_by_user_profile_idx" btree
(created_by_user_profile)
"input_document_dashboard_idx" btree (processing_state,
indexation_family_id, indexation_group_id, reception_id) INCLUDE
(active_content, archiving_state, creation_state) WHERE active_content =
true AND archiving_state <> 'DESTROYED'::text AND creation_state <>
'PENDING'::text
"input_document_fts_description_idx" gin
(to_tsvector('simple'::regconfig, description))
"input_document_fts_insured_firstname_idx" gin
(to_tsvector('simple'::regconfig, indexation_insured_firstname))
"input_document_fts_insured_lastname_idx" gin
(to_tsvector('simple'::regconfig, indexation_insured_lastname))
"input_document_indexation_activity_id_idx" btree
(indexation_activity_id)
"input_document_indexation_agency_id_idx" btree (indexation_agency_id)
"input_document_indexation_distributor_id_idx" btree
(indexation_distributor_id)
"input_document_indexation_domain_id_idx" btree (indexation_domain_id)
"input_document_indexation_family_id_idx" btree (indexation_family_id)
"input_document_indexation_group_id_idx" btree (indexation_group_id)
"input_document_indexation_insurer_id_idx" btree
(indexation_insurer_id)
"input_document_indexation_nature_id_idx" btree (indexation_nature_id)
"input_document_indexation_reference_idx" btree (indexation_reference)
"input_document_indexation_subsidiary_id_idx" btree
(indexation_subsidiary_id)
"input_document_indexation_warranty_id_idx" btree
(indexation_warranty_id)
"input_document_locked_by_user_idx" btree (locked_by_user)
"input_document_modified_at_idx" btree (modified_at)
"input_document_modified_by_user_profile_idx" btree
(modified_by_user_profile)
"input_document_processing_state_idx" btree (processing_state)
"input_document_stock_idx" btree (active_content, archiving_state,
creation_state, processing_state) WHERE active_content AND
archiving_state <> 'DESTROYED'::text AND creation_state <>
'PENDING'::text AND (processing_state = ANY
('{PENDING_PROCESSING,PENDING_INDEXATION,READY}'::text[]))
"input_dom_act_pi_idx" btree (indexation_activity_id,
indexation_domain_id) WHERE processing_state = 'PENDING_INDEXATION'::text
"input_dom_act_pp_idx" btree (indexation_activity_id,
indexation_domain_id) WHERE processing_state = 'PENDING_PROCESSING'::text
"input_dom_act_sub_idx" btree (indexation_activity_id,
indexation_domain_id, indexation_subsidiary_id)
"input_reception_id_created_at_idx" btree (reception_id, created_at)
"input_reception_id_reception_order_idx" btree (reception_id,
reception_order)
"operational_perimeter_view_idx" btree (processing_state,
indexation_distributor_id) WHERE processing_state =
'PENDING_PROCESSING'::text
Please find attached the 3 plans
explain_analyse_incremental_off.txt with enable_incremental_sort to off
explain_analyse_incremental_on.txt with enable_incremental_sort to on
explain_analyse_incremental_on_limit5000 with enable_incremental_sort to
on but with increase the limit to 5000, in this case plan choose don't
use `Incremental Sort`
The point that I don't understand in the plan (incremental_sort to on)
is the top level one, the limit cost doesn't seem right.
Limit (cost=324.05..16073.82 rows=50 width=44) (actual
time=1663688.290..1663696.151 rows=50 loops=1)
Buffers: shared hit=114672881 read=5725197 dirtied=38564 written=24394
I/O Timings: shared/local read=1481378.069 write=313.574
-> Incremental Sort (cost=324.05..27838050.13 rows=88375 width=44)
(actual time=1663688.289..1663696.144 rows=50 loops=1)
Have you a explaination on the behaviour ?
Best regards
--
Nicolas Lutic
Attachment | Content-Type | Size |
---|---|---|
explain_analyse_incremental_off.txt | text/plain | 15.6 KB |
explain_analyse_incremental_on.txt | text/plain | 18.2 KB |
explain_analyse_incremental_on_limit5000.txt | text/plain | 16.8 KB |
From | Date | Subject | |
---|---|---|---|
Next Message | shveta malik | 2023-12-12 08:44:09 | Re: How abnormal server shutdown could be detected by tests? |
Previous Message | Drouvot, Bertrand | 2023-12-12 08:23:46 | Add isCatalogRel in rmgrdesc |