From c81ded7cea94b60b698325ef2ef40ad832cfc043 Mon Sep 17 00:00:00 2001 From: Rucha Kulkarni Date: Wed, 3 Jun 2026 19:13:07 +0000 Subject: [PATCH 1/3] Optimize sys.indexes index_id computation for correlated subquery access Signed-off-by: Rucha Kulkarni --- contrib/babelfishpg_tsql/sql/sys_views.sql | 23 +++-- .../babelfishpg_tsql--6.1.0--6.2.0.sql | 94 +++++++++++++++++++ 2 files changed, 105 insertions(+), 12 deletions(-) diff --git a/contrib/babelfishpg_tsql/sql/sys_views.sql b/contrib/babelfishpg_tsql/sql/sys_views.sql index 8e13e48b298..ea2f25bb142 100644 --- a/contrib/babelfishpg_tsql/sql/sys_views.sql +++ b/contrib/babelfishpg_tsql/sql/sys_views.sql @@ -827,15 +827,6 @@ GRANT SELECT ON sys.identity_columns TO PUBLIC; create or replace view sys.indexes as -- Get all indexes from all system and user tables -with index_id_map as MATERIALIZED( - select - indexrelid, - case - when indisclustered then 1 - else 1+row_number() over(partition by indrelid order by indexrelid) - end as index_id - from pg_index -) select cast(X.indrelid as int) as object_id , cast( @@ -864,9 +855,17 @@ select , cast(0 as sys.bit) as has_filter , cast(null as sys.nvarchar) as filter_definition , cast(0 as sys.bit) as auto_created - , cast(imap.index_id as int) as index_id -from pg_index X -inner join index_id_map imap on imap.indexrelid = X.indexrelid + , cast( + case + when X.indisclustered then 1 + else 1 + (SELECT count(*) FROM pg_index x2 + WHERE x2.indrelid = X.indrelid + AND x2.indexrelid < X.indexrelid + AND NOT x2.indisclustered + AND x2.indislive) + end + as int) as index_id +from pg_index X inner join pg_class I on I.oid = X.indexrelid inner join pg_class ptbl on ptbl.oid = X.indrelid and ptbl.relispartition = false inner join pg_namespace nsp on nsp.oid = I.relnamespace diff --git a/contrib/babelfishpg_tsql/sql/upgrades/babelfishpg_tsql--6.1.0--6.2.0.sql b/contrib/babelfishpg_tsql/sql/upgrades/babelfishpg_tsql--6.1.0--6.2.0.sql index 19ec9e7a84f..1c4e7a20cc1 100644 --- a/contrib/babelfishpg_tsql/sql/upgrades/babelfishpg_tsql--6.1.0--6.2.0.sql +++ b/contrib/babelfishpg_tsql/sql/upgrades/babelfishpg_tsql--6.1.0--6.2.0.sql @@ -202,6 +202,100 @@ CREATE OR REPLACE AGGREGATE sys.tsql_select_for_xml_text_agg( FINALFUNC = tsql_query_to_xml_text_ffunc ); +create or replace view sys.indexes as +-- Get all indexes from all system and user tables +select + cast(X.indrelid as int) as object_id + , cast( + coalesce( + (select pg_catalog.string_agg( + case + when option like 'bbf_original_rel_name=%' then substring(option, 23 /* prefix length */) + else null + end, ',') + from unnest(I.reloptions) as option), + I.relname) + AS sys.sysname) AS name + , cast(case when X.indisclustered then 1 else 2 end as sys.tinyint) as type + , cast(case when X.indisclustered then 'CLUSTERED' else 'NONCLUSTERED' end as sys.nvarchar(60)) as type_desc + , cast(X.indisunique as sys.bit) as is_unique + , cast(case when ps.scheme_id is null then 1 else ps.scheme_id end as int) as data_space_id + , cast(0 as sys.bit) as ignore_dup_key + , cast(X.indisprimary as sys.bit) as is_primary_key + , cast(case when const.oid is null then 0 else 1 end as sys.bit) as is_unique_constraint + , cast(0 as sys.tinyint) as fill_factor + , cast(case when X.indpred is null then 0 else 1 end as sys.bit) as is_padded + , cast(case when X.indisready then 0 else 1 end as sys.bit) as is_disabled + , cast(0 as sys.bit) as is_hypothetical + , cast(1 as sys.bit) as allow_row_locks + , cast(1 as sys.bit) as allow_page_locks + , cast(0 as sys.bit) as has_filter + , cast(null as sys.nvarchar) as filter_definition + , cast(0 as sys.bit) as auto_created + , cast( + case + when X.indisclustered then 1 + else 1 + (SELECT count(*) FROM pg_index x2 + WHERE x2.indrelid = X.indrelid + AND x2.indexrelid < X.indexrelid + AND NOT x2.indisclustered + AND x2.indislive) + end + as int) as index_id +from pg_index X +inner join pg_class I on I.oid = X.indexrelid +inner join pg_class ptbl on ptbl.oid = X.indrelid and ptbl.relispartition = false +inner join pg_namespace nsp on nsp.oid = I.relnamespace +left join sys.babelfish_namespace_ext ext on (nsp.nspname = ext.nspname and ext.dbid = sys.db_id()) +left join sys.babelfish_partition_depend pd on + (ext.orig_name = pd.schema_name COLLATE sys.database_default + and CAST(ptbl.relname AS sys.nvarchar(128)) = pd.table_name COLLATE sys.database_default and pd.dbid = sys.db_id() and ptbl.relkind = 'p') +left join sys.babelfish_partition_scheme ps on (ps.partition_scheme_name = pd.partition_scheme_name and ps.dbid = sys.db_id()) +-- check if index is a unique constraint +left join pg_constraint const on const.conindid = I.oid and const.contype = 'u' +where +-- index is active +X.indislive +-- filter to get all the objects that belong to sys or babelfish schemas +and (nsp.nspname = 'sys' or ext.nspname is not null) + +union all +-- Create HEAP entries for each system and user table +select + cast(t.oid as int) as object_id + , cast(null as sys.sysname) as name + , cast(0 as sys.tinyint) as type + , cast('HEAP' as sys.nvarchar(60)) as type_desc + , cast(0 as sys.bit) as is_unique + , cast(case when ps.scheme_id is null then 1 else ps.scheme_id end as int) as data_space_id + , cast(0 as sys.bit) as ignore_dup_key + , cast(0 as sys.bit) as is_primary_key + , cast(0 as sys.bit) as is_unique_constraint + , cast(0 as sys.tinyint) as fill_factor + , cast(0 as sys.bit) as is_padded + , cast(0 as sys.bit) as is_disabled + , cast(0 as sys.bit) as is_hypothetical + , cast(1 as sys.bit) as allow_row_locks + , cast(1 as sys.bit) as allow_page_locks + , cast(0 as sys.bit) as has_filter + , cast(null as sys.nvarchar) as filter_definition + , cast(0 as sys.bit) as auto_created + , cast(0 as int) as index_id +from pg_class t +inner join pg_namespace nsp on nsp.oid = t.relnamespace +left join sys.babelfish_namespace_ext ext on (nsp.nspname = ext.nspname and ext.dbid = sys.db_id()) +left join sys.babelfish_partition_depend pd on + (ext.orig_name = pd.schema_name COLLATE sys.database_default + and CAST(t.relname AS sys.nvarchar(128)) = pd.table_name COLLATE sys.database_default and pd.dbid = sys.db_id()) +left join sys.babelfish_partition_scheme ps on (ps.partition_scheme_name = pd.partition_scheme_name and ps.dbid = sys.db_id()) +where (t.relkind = 'r' or t.relkind = 'p') +and t.relispartition = false +-- filter to get all the objects that belong to sys or babelfish schemas +and (nsp.nspname = 'sys' or ext.nspname is not null) +and has_table_privilege(t.oid, 'SELECT,INSERT,UPDATE,DELETE,TRUNCATE,TRIGGER') +order by object_id, type_desc; +GRANT SELECT ON sys.indexes TO PUBLIC; + -- Drops the temporary procedure used by the upgrade script. -- Please have this be one of the last statements executed in this upgrade script. DROP PROCEDURE sys.babelfish_drop_deprecated_object(varchar, varchar, varchar, varchar); From ecd68c517a75473b6e29f2013c4ae66703c47219 Mon Sep 17 00:00:00 2001 From: Rucha Kulkarni Date: Wed, 3 Jun 2026 19:44:30 +0000 Subject: [PATCH 2/3] Remove extra filters from index_id scalar subquery Signed-off-by: Rucha Kulkarni --- contrib/babelfishpg_tsql/sql/sys_views.sql | 4 +--- .../sql/upgrades/babelfishpg_tsql--6.1.0--6.2.0.sql | 4 +--- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/contrib/babelfishpg_tsql/sql/sys_views.sql b/contrib/babelfishpg_tsql/sql/sys_views.sql index ea2f25bb142..db67cc4a016 100644 --- a/contrib/babelfishpg_tsql/sql/sys_views.sql +++ b/contrib/babelfishpg_tsql/sql/sys_views.sql @@ -860,9 +860,7 @@ select when X.indisclustered then 1 else 1 + (SELECT count(*) FROM pg_index x2 WHERE x2.indrelid = X.indrelid - AND x2.indexrelid < X.indexrelid - AND NOT x2.indisclustered - AND x2.indislive) + AND x2.indexrelid < X.indexrelid) end as int) as index_id from pg_index X diff --git a/contrib/babelfishpg_tsql/sql/upgrades/babelfishpg_tsql--6.1.0--6.2.0.sql b/contrib/babelfishpg_tsql/sql/upgrades/babelfishpg_tsql--6.1.0--6.2.0.sql index 2c855b7a223..da3da38534a 100644 --- a/contrib/babelfishpg_tsql/sql/upgrades/babelfishpg_tsql--6.1.0--6.2.0.sql +++ b/contrib/babelfishpg_tsql/sql/upgrades/babelfishpg_tsql--6.1.0--6.2.0.sql @@ -243,9 +243,7 @@ select when X.indisclustered then 1 else 1 + (SELECT count(*) FROM pg_index x2 WHERE x2.indrelid = X.indrelid - AND x2.indexrelid < X.indexrelid - AND NOT x2.indisclustered - AND x2.indislive) + AND x2.indexrelid < X.indexrelid) end as int) as index_id from pg_index X From 5eb6df50751ab8dcf8fb7686c1f2108c4d086e80 Mon Sep 17 00:00:00 2001 From: Rucha Kulkarni Date: Thu, 4 Jun 2026 01:50:03 +0000 Subject: [PATCH 3/3] Correcting index_id logic Signed-off-by: Rucha Kulkarni --- contrib/babelfishpg_tsql/sql/sys_views.sql | 2 +- .../sql/upgrades/babelfishpg_tsql--6.1.0--6.2.0.sql | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/contrib/babelfishpg_tsql/sql/sys_views.sql b/contrib/babelfishpg_tsql/sql/sys_views.sql index db67cc4a016..a0c101a7337 100644 --- a/contrib/babelfishpg_tsql/sql/sys_views.sql +++ b/contrib/babelfishpg_tsql/sql/sys_views.sql @@ -858,7 +858,7 @@ select , cast( case when X.indisclustered then 1 - else 1 + (SELECT count(*) FROM pg_index x2 + else 2 + (SELECT count(*) FROM pg_index x2 WHERE x2.indrelid = X.indrelid AND x2.indexrelid < X.indexrelid) end diff --git a/contrib/babelfishpg_tsql/sql/upgrades/babelfishpg_tsql--6.1.0--6.2.0.sql b/contrib/babelfishpg_tsql/sql/upgrades/babelfishpg_tsql--6.1.0--6.2.0.sql index da3da38534a..6894f167923 100644 --- a/contrib/babelfishpg_tsql/sql/upgrades/babelfishpg_tsql--6.1.0--6.2.0.sql +++ b/contrib/babelfishpg_tsql/sql/upgrades/babelfishpg_tsql--6.1.0--6.2.0.sql @@ -241,7 +241,7 @@ select , cast( case when X.indisclustered then 1 - else 1 + (SELECT count(*) FROM pg_index x2 + else 2 + (SELECT count(*) FROM pg_index x2 WHERE x2.indrelid = X.indrelid AND x2.indexrelid < X.indexrelid) end