I have to create a complete view of BTree index list to analyze the performances of each and to flush out abnormal indexes (includes or equivalent) to drop them…
Nevertheless I cannot find a way to have the list of the columns involved in the INCLUDE part of index definition.
Also I need index filter part for indexes having it, but I don’t found any information in the tables and views of the pg_catalog definition…
The query I use to try is this is one:
SELECT --i.indexrelid,
s.nspname AS "TABLE_SCHEMA", tc.relname AS "TABLE_NAME",
ic.relname AS "INDEX_NAME", m.amname as "INDEX_TYPE",
(SELECT STRING_AGG(a.attname ||
CASE
WHEN indoption[a.attnum-1] = 3
THEN ' DESC'
ELSE ' ASC'
END ||
CASE
WHEN i.indcollation[attnum-1] = 0
THEN ''
ELSE ' COLLATE ' ||
(SELECT collname
FROM pg_collation
WHERE oid = i.indcollation[attnum-1])
END, ', ')
FROM pg_attribute AS a
WHERE a.attrelid = i.indexrelid) AS "KEY_COLUMN_LIST",
i.indisunique AS "UNIQUE",
i.indisprimary AS "PRIMARY_KEY",
i.indisclustered AS "CLUSTERED",
i.indisvalid AS "VALID",
CASE k.contype
WHEN 'c' THEN 'CHECK'
WHEN 'f' THEN 'FOREIGN KEY'
WHEN 'p' THEN 'PRIMARY KEY'
WHEN 'u' THEN 'UNIQUE'
END AS "CONSTRAINT_TYPE",
--> ??? AS "INCLUDE_COLUM_LIST" attnum <= 0 suppose to have all other columns...
(SELECT STRING_AGG(a2.attname, ', ')
FROM pg_attribute AS a2
WHERE a2.attrelid = i.indexrelid
AND a2.attnum <= 0) AS "INCLUDE_COLUM_LIST",
-- does not works
--> ??? AS "FILTER_DEFINITION"
--> I did not find
pg_get_indexdef(i.indexrelid) AS "INDEX_DEFINITION"
FROM pg_index AS i -- index
JOIN pg_class AS ic -- classe index
ON i.indexrelid = ic.oid
JOIN pg_class AS tc -- classe table
ON i.indrelid = tc.oid
JOIN pg_namespace AS s -- schema
ON tc.relnamespace = s.oid
JOIN pg_am AS m -- type d'index
ON ic.relam = m.oid
LEFT OUTER JOIN pg_constraint AS k -- contraintes associées
ON i.indexrelid = k.conindid AND i.indkey[0:indnkeyatts-1] = k.conkey
WHERE m.amname = 'btree'
-- AND ic.relname LIKE 'x%' --> to match with my sample
ORDER BY 1, 2, 3, 4
For my demo I create this table and those indexes:
CREATE TABLE TX (A INT, B INT, C INT, D INT, E VARCHAR(32), F INT, G DATE, H BOOLEAN)
CREATE INDEX X1 ON TX (A DESC, B ASC, C DESC)
CREATE INDEX X2 ON TX (A, C) INCLUDE (D, E, F)
CREATE INDEX X3 ON TX (B) WHERE G > '2020-01-01'
Of course I could parse the INDEX_DEFINITION but there is no garanty that ever works with a simple SUBSTRING… And I dont’ want to incluse Lex and Yacc into a simple query !!! 😉
2
Answers
Actually I have parse the index_def with this SQL code :
But I will surely use @Zegarek solution which seems the best !
The
indnkeyatts
column inpg_catalog.pg_index
can tell you which columns are key or non-key (payload) as described in thecreate index
doc)As to the index predicate, there’s a
pg_get_expr()
function for that because it’s stored aspg_node_tree
, not regulartext
inpg_index
:Demo at db<>fiddle with above added to your
select
returns:If
psql
d+
meta-command can fetch you something, so can you: just start it with-E
and it’ll begin to print all queries it used to show you the information you request:The queries above can be obtained from what you get if you do
d+
on any of your indexes withECHO_HIDDEN
seton
.