add the idea Inverting the recursion of the CTE-query, combined with the type condition.

This commit is contained in:
Michael Hoennig 2024-08-23 06:52:15 +02:00
parent 77676c9217
commit cad8b475f8
2 changed files with 97 additions and 38 deletions

View File

@ -390,6 +390,14 @@ We found some solution approaches:
See chapter below. See chapter below.
3. Inverting the recursion of the CTE-query, combined with the type condition.
Instead of starting the recursion with `currentsubjectsuuids()`,
we could start it with the target table name and row-type,
then recurse down to the `currentsubjectsuuids()`.
This idea was not yet explored.
### Adding The Object Type To The Table `rbacObject` ### Adding The Object Type To The Table `rbacObject`
@ -423,7 +431,7 @@ I also moved the function call which determines into its own WITH-section, with
Experimentally I moved the business condition into the CTE SELECT, also with no improvement. Experimentally I moved the business condition into the CTE SELECT, also with no improvement.
Such rearrangements seem to be sucessfully done by the PostgreSQL query optimizer. Such rearrangements seem to be successfully done by the PostgreSQL query optimizer.
## Summary ## Summary

View File

@ -4,11 +4,12 @@ select * from hs_statistics_view;
-- ======================================================== -- ========================================================
-- An example for a restricted view (_rv) as generated by our RBAC system: -- This is the extracted recursive CTE query to determine the visible object UUIDs of a single table
drop view if exists hs_hosting_asset_example_rv; -- (and optionally the hosting-asset-type) as a separate VIEW.
create view hs_hosting_asset_example_rv as -- In the generated code this is part of the hs_hosting_asset_rv VIEW.
with accessible_hs_hosting_asset_uuids as (
drop view if exists hs_hosting_asset_example_gv;
create view hs_hosting_asset_example_gv as
with recursive with recursive
recursive_grants as ( recursive_grants as (
select distinct rbacgrants.descendantuuid, select distinct rbacgrants.descendantuuid,
@ -40,16 +41,43 @@ create view hs_hosting_asset_example_rv as
join rbacobject obj on obj.uuid = perm.objectuuid join rbacobject obj on obj.uuid = perm.objectuuid
join count_check cc on cc.valid join count_check cc on cc.valid
where obj.objecttable::text = 'hs_hosting_asset'::text where obj.objecttable::text = 'hs_hosting_asset'::text
and obj.type = 'EMAIL_ADDRESS'::hshostingassettype -- with/without this type condition -- with/without this type condition
-- and obj.type = 'EMAIL_ADDRESS'::hshostingassettype
and obj.type = 'EMAIL_ADDRESS'::hshostingassettype
;
-- -----------------------------------------------------------------------------------------------
-- A query just on the above view, only determining visible objects, no JOIN with business data:
rollback transaction;
begin transaction;
CALL defineContext('performance testing', null, 'superuser-alex@hostsharing.net',
'hs_booking_project#D-1000000-hshdefaultproject:ADMIN');
-- 'hs_booking_project#D-1000300-mihdefaultproject:ADMIN');
SET TRANSACTION READ ONLY;
EXPLAIN ANALYZE select * from hs_hosting_asset_example_gv;
end transaction ;
-- ========================================================
-- An example for a restricted view (_rv) similar to the one generated by our RBAC system,
-- but using the above separate VIEW to determine the visible objects.
drop view if exists hs_hosting_asset_example_rv;
create view hs_hosting_asset_example_rv as
with accessible_hs_hosting_asset_uuids as (
select * from hs_hosting_asset_example_gv
) )
select target.* select target.*
from hs_hosting_asset target from hs_hosting_asset target
where (target.uuid in (select accessible_hs_hosting_asset_uuids.objectuuid where (target.uuid in (select accessible_hs_hosting_asset_uuids.objectuuid
from accessible_hs_hosting_asset_uuids)); from accessible_hs_hosting_asset_uuids));
-- end of the example view.
-- ------------------------------------------------------------------------------- -- -------------------------------------------------------------------------------
-- performing several queries on the above view to determine average performance:
rollback transaction; rollback transaction;
DO language plpgsql $$ DO language plpgsql $$
DECLARE DECLARE
@ -90,9 +118,32 @@ $$;
-- average seconds per recursive CTE select as role 'hs_hosting_asset:<DEBITOR>defaultproject:ADMIN' -- average seconds per recursive CTE select as role 'hs_hosting_asset:<DEBITOR>defaultproject:ADMIN'
-- joined with business query for all 'EMAIL_ADDRESSES': -- joined with business query for all 'EMAIL_ADDRESSES':
-- D-1000000-hsh D-1000300-mih -- D-1000000-hsh D-1000300-mih
-- - without type comparision in rbacobject: ~3.30 - ~3.49 ~0.23 -- - without type comparison in rbacobject: ~3.30 - ~3.49 ~0.23
-- - with type comparision in rbacobject: ~2.99 - ~3.08 ~0.21 -- - with type comparison in rbacobject: ~2.99 - ~3.08 ~0.21
-- -------------------------------------------------------------------------------
-- and a single query, so EXPLAIN can be used
rollback transaction;
begin transaction;
CALL defineContext('performance testing', null, 'superuser-alex@hostsharing.net',
'hs_booking_project#D-1000000-hshdefaultproject:ADMIN');
-- 'hs_booking_project#D-1000300-mihdefaultproject:ADMIN');
SET TRANSACTION READ ONLY;
EXPLAIN SELECT * from (
-- An example for a business query based on the view:
select type, uuid, identifier, caption
from hs_hosting_asset_example_rv
where type = 'EMAIL_ADDRESS'
-- and identifier like 'b%'
-- end of the business query example.
) ha;
end transaction;
-- ============================================================================= -- =============================================================================