Problem:
I have noticed recently, that after updates on a larger number of hosts it takes a while until upgradable package counts get updated. I can see that a lot of “Bulk generate applicability for hosts” are running for several minutes, sometimes more than 20 minutes. I see also that postgres is very busy. The postgres logs contain long running queries.
Expected outcome:
Faster “Bulk generate applicability for hosts” runs
Foreman and Proxy versions:
foreman-3.14.0-1.el9.noarch
katello-4.16.1-1.el9.noarch
Distribution and version:
AlmaLinux 9.6
Other relevant data:
In the postgres logs I can find a lot of queries like the following which take approx. one minute each. Each query seems to be for each host after each update task. I guess, that’s the reason why it takes so long:
2025-06-23 07:14:54 CEST LOG: duration: 49038.861 ms execute <unnamed>: SELECT "katello_rpms"."id" FROM "katello_rpms" INNER JOIN katello_repository_rpms ON
katello_rpms.id = katello_repository_rpms.rpm_id INNER JOIN katello_installed_packages ON
katello_rpms.name = katello_installed_packages.name AND
katello_rpms.arch = katello_installed_packages.arch AND
katello_rpms.evr > katello_installed_packages.evr AND
katello_installed_packages.id in (SELECT DISTINCT ON (katello_installed_packages.name, katello_installed_packages.arch) katello_installed_packages.id FROM katello_installed_packages INNER JOIN katello_host_installed_packages ON katello_installed_packages.id = katello_host_installed_packages.installed_package_id WHERE katello_host_installed_packages.host_id = 347 ORDER BY katello_installed_packages.name, katello_installed_packages.arch, katello_installed_packages.evr DESC) LEFT JOIN katello_module_stream_rpms ON
katello_rpms.id = katello_module_stream_rpms.rpm_id INNER JOIN katello_host_installed_packages ON
katello_installed_packages.id = katello_host_installed_packages.installed_package_id WHERE (katello_repository_rpms.repository_id in (1971,16489,28501,16492,16491,16490,16493,190048,226614)) AND (katello_host_installed_packages.host_id = 347) AND ((katello_module_stream_rpms.module_stream_id IS NULL AND
katello_installed_packages.id NOT IN (SELECT "katello_installed_packages"."id" FROM "katello_installed_packages" WHERE 1=0 AND 1=0)) OR
(katello_module_stream_rpms.module_stream_id IN (SELECT "katello_module_streams"."id" FROM "katello_module_streams" inner join katello_available_module_streams on
katello_module_streams.name = katello_available_module_streams.name and
katello_module_streams.stream = katello_available_module_streams.stream and
katello_module_streams.context = katello_available_module_streams.context inner join katello_host_available_module_streams on
katello_available_module_streams.id = katello_host_available_module_streams.available_module_stream_id WHERE (katello_host_available_module_streams.host_id = 347 and
katello_host_available_module_streams.status = 'enabled'))
AND katello_installed_packages.id IN (SELECT "katello_installed_packages"."id" FROM "katello_installed_packages" WHERE 1=0 AND 1=0)))
2025-06-23 07:14:58 CEST LOG: duration: 48128.038 ms execute <unnamed>: SELECT "katello_rpms"."id" FROM "katello_rpms" INNER JOIN katello_repository_rpms ON
katello_rpms.id = katello_repository_rpms.rpm_id INNER JOIN katello_installed_packages ON
katello_rpms.name = katello_installed_packages.name AND
katello_rpms.arch = katello_installed_packages.arch AND
katello_rpms.evr > katello_installed_packages.evr AND
katello_installed_packages.id in (SELECT DISTINCT ON (katello_installed_packages.name, katello_installed_packages.arch) katello_installed_packages.id FROM katello_installed_packages INNER JOIN katello_host_installed_packages ON katello_installed_packages.id = katello_host_installed_packages.installed_package_id WHERE katello_host_installed_packages.host_id = 284 ORDER BY katello_installed_packages.name, katello_installed_packages.arch, katello_installed_packages.evr DESC) LEFT JOIN katello_module_stream_rpms ON
katello_rpms.id = katello_module_stream_rpms.rpm_id INNER JOIN katello_host_installed_packages ON
katello_installed_packages.id = katello_host_installed_packages.installed_package_id WHERE (katello_repository_rpms.repository_id in (16490,16491,16489,16492,28501,1971,16493,190048,226614)) AND (katello_host_installed_packages.host_id = 284) AND ((katello_module_stream_rpms.module_stream_id IS NULL AND
katello_installed_packages.id NOT IN (SELECT "katello_installed_packages"."id" FROM "katello_installed_packages" WHERE 1=0 AND 1=0)) OR
(katello_module_stream_rpms.module_stream_id IN (SELECT "katello_module_streams"."id" FROM "katello_module_streams" inner join katello_available_module_streams on
katello_module_streams.name = katello_available_module_streams.name and
katello_module_streams.stream = katello_available_module_streams.stream and
katello_module_streams.context = katello_available_module_streams.context inner join katello_host_available_module_streams on
katello_available_module_streams.id = katello_host_available_module_streams.available_module_stream_id WHERE (katello_host_available_module_streams.host_id = 284 and
katello_host_available_module_streams.status = 'enabled'))
AND katello_installed_packages.id IN (SELECT "katello_installed_packages"."id" FROM "katello_installed_packages" WHERE 1=0 AND 1=0)))
Postgres explain analyze for the second query above:
foreman=# explain analyze SELECT "katello_rpms"."id" FROM "katello_rpms" INNER JOIN katello_repository_rpms ON
katello_rpms.id = katello_repository_rpms.rpm_id INNER JOIN katello_installed_packages ON
katello_rpms.name = katello_installed_packages.name AND
katello_rpms.arch = katello_installed_packages.arch AND
katello_rpms.evr > katello_installed_packages.evr AND
katello_installed_packages.id in (SELECT DISTINCT ON (katello_installed_packages.name, katello_installed_packages.arch) katello_installed_packages.id FROM katello_installed_packages INNER JOIN katello_host_installed_packages ON katello_installed_packages.id = katello_host_installed_packages.installed_package_id WHERE katello_host_installed_packages.host_id = 284 ORDER BY katello_installed_packages.name, katello_installed_packages.arch, katello_installed_packages.evr DESC) LEFT JOIN katello_module_stream_rpms ON
katello_rpms.id = katello_module_stream_rpms.rpm_id INNER JOIN katello_host_installed_packages ON
katello_installed_packages.id = katello_host_installed_packages.installed_package_id WHERE (katello_repository_rpms.repository_id in (16490,16491,16489,16492,28501,1971,16493,190048,226614)) AND (katello_host_installed_packages.host_id = 284) AND ((katello_module_stream_rpms.module_stream_id IS NULL AND
katello_installed_packages.id NOT IN (SELECT "katello_installed_packages"."id" FROM "katello_installed_packages" WHERE 1=0 AND 1=0)) OR
(katello_module_stream_rpms.module_stream_id IN (SELECT "katello_module_streams"."id" FROM "katello_module_streams" inner join katello_available_module_streams on
katello_module_streams.name = katello_available_module_streams.name and
katello_module_streams.stream = katello_available_module_streams.stream and
katello_module_streams.context = katello_available_module_streams.context inner join katello_host_available_module_streams on
katello_available_module_streams.id = katello_host_available_module_streams.available_module_stream_id WHERE (katello_host_available_module_streams.host_id = 284 and
katello_host_available_module_streams.status = 'enabled'))
AND katello_installed_packages.id IN (SELECT "katello_installed_packages"."id" FROM "katello_installed_packages" WHERE 1=0 AND 1=0)));
QUERY PLAN
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-----------------------------------------------------------------------
Nested Loop (cost=5098.04..56858.95 rows=3 width=4) (actual time=12117.250..50681.607 rows=6 loops=1)
-> Nested Loop Left Join (cost=5097.61..56842.45 rows=17 width=4) (actual time=94.264..50662.319 rows=1656 loops=1)
Filter: (((katello_module_stream_rpms.module_stream_id IS NULL) AND (NOT (hashed SubPlan 1))) OR ((hashed SubPlan 2) AND (hashed SubPlan 3)))
Rows Removed by Filter: 499
-> Nested Loop (cost=4901.74..56622.24 rows=67 width=8) (actual time=94.189..50640.951 rows=2147 loops=1)
-> Nested Loop (cost=4901.31..6525.93 rows=8 width=324) (actual time=6.866..20.550 rows=619 loops=1)
Join Filter: ("ANY_subquery".id = katello_installed_packages.id)
-> Hash Join (cost=4901.02..6075.39 rows=82 width=8) (actual time=6.841..11.337 rows=619 loops=1)
Hash Cond: (katello_host_installed_packages.installed_package_id = "ANY_subquery".id)
-> Bitmap Heap Scan on katello_host_installed_packages (cost=13.59..1185.20 rows=667 width=4) (actual time=0.091..1.670 rows=627 loops=1)
Recheck Cond: (host_id = 284)
Heap Blocks: exact=67
-> Bitmap Index Scan on katello_host_installed_packages_host_id (cost=0.00..13.42 rows=667 width=0) (actual time=0.075..0.076 rows=664 loops=1)
Index Cond: (host_id = 284)
-> Hash (cost=4884.93..4884.93 rows=200 width=4) (actual time=6.725..6.734 rows=619 loops=1)
Buckets: 1024 Batches: 1 Memory Usage: 30kB
-> HashAggregate (cost=4882.93..4884.93 rows=200 width=4) (actual time=6.334..6.523 rows=619 loops=1)
Group Key: "ANY_subquery".id
Batches: 1 Memory Usage: 89kB
-> Subquery Scan on "ANY_subquery" (cost=4869.59..4881.26 rows=667 width=4) (actual time=5.118..6.033 rows=619 loops=1)
-> Unique (cost=4869.59..4874.59 rows=667 width=324) (actual time=5.116..5.688 rows=619 loops=1)
-> Sort (cost=4869.59..4871.26 rows=667 width=324) (actual time=5.114..5.278 rows=627 loops=1)
Sort Key: katello_installed_packages_1.name, katello_installed_packages_1.arch, katello_installed_packages_1.evr DESC
Sort Method: quicksort Memory: 345kB
-> Nested Loop (cost=13.88..4838.30 rows=667 width=324) (actual time=0.080..3.694 rows=627 loops=1)
-> Bitmap Heap Scan on katello_host_installed_packages katello_host_installed_packages_1 (cost=13.59..1185.20 rows=667 width=4) (actual time=0.049..0.675 rows=627 loops=1)
Recheck Cond: (host_id = 284)
Heap Blocks: exact=67
-> Bitmap Index Scan on katello_host_installed_packages_host_id (cost=0.00..13.42 rows=667 width=0) (actual time=0.040..0.041 rows=664 loops=1)
Index Cond: (host_id = 284)
-> Index Scan using katello_installed_packages_pkey on katello_installed_packages katello_installed_packages_1 (cost=0.29..5.48 rows=1 width=324) (actual time=0.004..0.004
rows=1 loops=627)
Index Cond: (id = katello_host_installed_packages_1.installed_package_id)
-> Index Scan using katello_installed_packages_pkey on katello_installed_packages (cost=0.29..5.48 rows=1 width=324) (actual time=0.009..0.009 rows=1 loops=619)
Index Cond: (id = katello_host_installed_packages.installed_package_id)
Filter: ((NOT (hashed SubPlan 1)) OR (hashed SubPlan 3))
SubPlan 1
-> Result (cost=0.00..0.00 rows=0 width=0) (actual time=0.001..0.001 rows=0 loops=2)
One-Time Filter: false
SubPlan 3
-> Result (cost=0.00..0.00 rows=0 width=0) (never executed)
One-Time Filter: false
-> Index Scan using katello_rpms_fields_index on katello_rpms (cost=0.42..6262.03 rows=1 width=331) (actual time=73.828..81.768 rows=3 loops=619)
Index Cond: (((name)::text = (katello_installed_packages.name)::text) AND ((arch)::text = (katello_installed_packages.arch)::text))
Filter: (evr > katello_installed_packages.evr)
Rows Removed by Filter: 48
-> Index Scan using katello_msrpm_rpm_idx on katello_module_stream_rpms (cost=0.29..0.33 rows=2 width=16) (actual time=0.006..0.006 rows=0 loops=2147)
Index Cond: (rpm_id = katello_rpms.id)
SubPlan 2
-> Nested Loop (cost=0.56..195.58 rows=1 width=8) (actual time=0.052..0.054 rows=0 loops=1)
Join Filter: (((katello_available_module_streams.name)::text = (katello_module_streams.name)::text) AND ((katello_available_module_streams.stream)::text = (katello_module_streams.stream)::text) AND ((katello_available_mo
dule_streams.context)::text = (katello_module_streams.context)::text))
-> Nested Loop (cost=0.56..16.79 rows=1 width=21) (actual time=0.051..0.053 rows=0 loops=1)
-> Index Only Scan using rpm_and_module_applicability_related_indices on katello_host_available_module_streams (cost=0.29..8.49 rows=1 width=8) (actual time=0.050..0.051 rows=0 loops=1)
Index Cond: ((host_id = 284) AND (status = 'enabled'::text))
Heap Fetches: 0
-> Index Scan using katello_available_module_streams_pkey on katello_available_module_streams (cost=0.28..8.29 rows=1 width=29) (never executed)
Index Cond: (id = katello_host_available_module_streams.available_module_stream_id)
-> Seq Scan on katello_module_streams (cost=0.00..133.74 rows=2574 width=29) (never executed)
-> Index Only Scan using index_katello_repository_rpms_on_rpm_id_and_repository_id on katello_repository_rpms (cost=0.43..0.96 rows=1 width=4) (actual time=0.009..0.009 rows=0 loops=1656)
Index Cond: (rpm_id = katello_rpms.id)
Filter: (repository_id = ANY ('{16490,16491,16489,16492,28501,1971,16493,190048,226614}'::integer[]))
Rows Removed by Filter: 6
Heap Fetches: 66
Planning Time: 2.646 ms
Execution Time: 50681.855 ms
(64 rows)