Skip to content

Instantly share code, notes, and snippets.

@thomasdarimont
Last active April 19, 2018 17:43
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save thomasdarimont/992aaad6af704f40fd4483af3d42290e to your computer and use it in GitHub Desktop.
Save thomasdarimont/992aaad6af704f40fd4483af3d42290e to your computer and use it in GitHub Desktop.
Find Candidate Columns to index in postgresql keycloak database
-- check for FKs where there is no matching index
-- on the referencing side
-- or a bad index
WITH fk_actions ( code, action ) AS (
VALUES ( 'a', 'error' ),
( 'r', 'restrict' ),
( 'c', 'cascade' ),
( 'n', 'set null' ),
( 'd', 'set default' )
),
fk_list AS (
SELECT pg_constraint.oid as fkoid, conrelid, confrelid as parentid,
conname, relname, nspname,
fk_actions_update.action as update_action,
fk_actions_delete.action as delete_action,
conkey as key_cols
FROM pg_constraint
JOIN pg_class ON conrelid = pg_class.oid
JOIN pg_namespace ON pg_class.relnamespace = pg_namespace.oid
JOIN fk_actions AS fk_actions_update ON confupdtype = fk_actions_update.code
JOIN fk_actions AS fk_actions_delete ON confdeltype = fk_actions_delete.code
WHERE contype = 'f'
),
fk_attributes AS (
SELECT fkoid, conrelid, attname, attnum
FROM fk_list
JOIN pg_attribute
ON conrelid = attrelid
AND attnum = ANY( key_cols )
ORDER BY fkoid, attnum
),
fk_cols_list AS (
SELECT fkoid, array_agg(attname) as cols_list
FROM fk_attributes
GROUP BY fkoid
),
index_list AS (
SELECT indexrelid as indexid,
pg_class.relname as indexname,
indrelid,
indkey,
indpred is not null as has_predicate,
pg_get_indexdef(indexrelid) as indexdef
FROM pg_index
JOIN pg_class ON indexrelid = pg_class.oid
WHERE indisvalid
),
fk_index_match AS (
SELECT fk_list.*,
indexid,
indexname,
indkey::int[] as indexatts,
has_predicate,
indexdef,
array_length(key_cols, 1) as fk_colcount,
array_length(indkey,1) as index_colcount,
round(pg_relation_size(conrelid)/(1024^2)::numeric) as table_mb,
cols_list
FROM fk_list
JOIN fk_cols_list USING (fkoid)
LEFT OUTER JOIN index_list
ON conrelid = indrelid
AND (indkey::int2[])[0:(array_length(key_cols,1) -1)] @> key_cols
),
fk_perfect_match AS (
SELECT fkoid
FROM fk_index_match
WHERE (index_colcount - 1) <= fk_colcount
AND NOT has_predicate
AND indexdef LIKE '%USING btree%'
),
fk_index_check AS (
SELECT 'no index' as issue, *, 1 as issue_sort
FROM fk_index_match
WHERE indexid IS NULL
UNION ALL
SELECT 'questionable index' as issue, *, 2
FROM fk_index_match
WHERE indexid IS NOT NULL
AND fkoid NOT IN (
SELECT fkoid
FROM fk_perfect_match)
),
parent_table_stats AS (
SELECT fkoid, tabstats.relname as parent_name,
(n_tup_ins + n_tup_upd + n_tup_del + n_tup_hot_upd) as parent_writes,
round(pg_relation_size(parentid)/(1024^2)::numeric) as parent_mb
FROM pg_stat_user_tables AS tabstats
JOIN fk_list
ON relid = parentid
),
fk_table_stats AS (
SELECT fkoid,
(n_tup_ins + n_tup_upd + n_tup_del + n_tup_hot_upd) as writes,
seq_scan as table_scans
FROM pg_stat_user_tables AS tabstats
JOIN fk_list
ON relid = conrelid
)
SELECT nspname as schema_name,
relname as table_name,
conname as fk_name,
issue,
table_mb,
writes,
table_scans,
parent_name,
parent_mb,
parent_writes,
cols_list,
indexdef
FROM fk_index_check
JOIN parent_table_stats USING (fkoid)
JOIN fk_table_stats USING (fkoid)
--WHERE table_mb > 9
-- AND ( writes > 1000
-- OR parent_writes > 1000
-- OR parent_mb > 10 )
ORDER BY issue_sort, table_mb DESC, table_name, fk_name;
schema_name table_name fk_name issue table_mb writes table_scans parent_name parent_mb parent_writes cols_list indexdef
public authentication_execution fk_auth_exec_flow no index 0 56 663 authentication_flow 0 22 {flow_id}
public authentication_execution fk_auth_exec_realm no index 0 56 663 realm 0 107 {realm_id}
public authentication_flow fk_auth_flow_realm no index 0 22 171 realm 0 107 {realm_id}
public authenticator_config fk_auth_realm no index 0 4 77 realm 0 107 {realm_id}
public client fk_cli_tmplt_client no index 0 52 249 client_template 0 3 {client_template_id}
public client_default_roles fk_nuilts7klwqw2h8m2b5joytky no index 0 8 194 client 0 52 {client_id}
public client_identity_prov_mapping fk_56elwnibji49avxsrtuf6xj23 no index 0 0 20 client 0 52 {client_id}
public client_session fk_b4ao2vcvat6ukau74wbwtfqo1 no index 0 0 43 user_session 0 0 {session_id}
public composite_role fk_a63wvekftu8jo1pnj81e7mce2 no index 0 769 652 keycloak_role 0 148 {composite}
public composite_role fk_gr7thllb9lu8q4vqa4524jjy8 no index 0 769 652 keycloak_role 0 148 {child_role}
public credential fk_pfyr0glasqyl0dei3kl69r6v0 no index 0 13 138 user_entity 0 26 {user_id}
public federated_identity fk404288b92ef007a6 no index 0 0 19 user_entity 0 26 {user_id}
public group_attribute fk_group_attribute_group no index 0 0 19 keycloak_group 0 0 {group_id}
public group_role_mapping fk_group_role_group no index 0 0 20 keycloak_group 0 0 {group_id}
public identity_provider fk2b4ebc52ae5c3b34 no index 0 0 35 realm 0 107 {realm_id}
public identity_provider_mapper fk_idpm_realm no index 0 0 79 realm 0 107 {realm_id}
public keycloak_group fk_group_realm no index 0 0 126 realm 0 107 {realm_id}
public keycloak_role fk_6vyqfe4cn4wlq8r6kt5vdsj5c no index 0 148 1322 realm 0 107 {realm}
public keycloak_role fk_kjho5le2c0ral09fl8cm9wfw9 no index 0 148 1322 client 0 52 {client}
public protocol_mapper fk_cli_tmplt_mapper no index 0 87 291 client_template 0 3 {client_template_id}
public protocol_mapper fk_pcm_realm no index 0 87 291 client 0 52 {client_id}
public realm fk_traf444kk6qrkms7n56aiwq5y no index 0 107 4766 client 0 52 {master_admin_client}
public realm_attribute fk_8shxd6l3e9atqukacxgpffptw no index 0 24 90 realm 0 107 {realm_id}
public realm_default_groups fk_def_groups_realm no index 0 0 78 realm 0 107 {realm_id}
public realm_default_roles fk_evudb1ppw84oxfax2drs03icc no index 0 2 91 realm 0 107 {realm_id}
public realm_enabled_event_types fk_h846o4h0w8epx5nwedrf5y69j no index 0 350 92 realm 0 107 {realm_id}
public realm_events_listeners fk_h846o4h0w8epx5nxev9f5y69j no index 0 34 92 realm 0 107 {realm_id}
public realm_supported_locales fk_supported_locales_realm no index 0 51 89 realm 0 107 {realm_id}
public redirect_uris fk_1burs8pb4ouj97h5wuppahv9f no index 0 30 197 client 0 52 {client_id}
public required_action_provider fk_req_act_realm no index 0 10 77 realm 0 107 {realm_id}
public scope_mapping fk_p3rh9grku11kqfrs4fltt7rnq no index 0 4 115 keycloak_role 0 148 {role_id}
public template_scope_mapping fk_templ_scope_role no index 0 2 34 keycloak_role 0 148 {role_id}
public user_attribute fk_5hrm2vlf9ql5fu043kqepovbr no index 0 7 154 user_entity 0 26 {user_id}
public user_consent fk_grntcsnt_user no index 0 0 22 user_entity 0 26 {user_id}
public user_federation_mapper fk_fedmapperpm_fedprv no index 0 0 79 user_federation_provider 0 0 {federation_provider_id}
public user_federation_mapper fk_fedmapperpm_realm no index 0 0 79 realm 0 107 {realm_id}
public user_federation_provider fk_1fj32f6ptolw2qy60cd8n01e8 no index 0 0 93 realm 0 107 {realm_id}
public user_group_membership fk_user_group_user no index 0 0 19 user_entity 0 26 {user_id}
public user_required_action fk_6qj3w1jw9cvafhe19bwsiuvmd no index 0 0 23 user_entity 0 26 {user_id}
public user_role_mapping fk_c4fqv34p1mbylloxang7b1q3l no index 0 35 155 user_entity 0 26 {user_id}
public web_origins fk_lojpho213xcx4wnkog82ssrfy no index 0 24 198 client 0 52 {client_id}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment