ver uso usar tipos reconstruir optimizar manejo index create consultas consulta sql postgresql indexing

sql - usar - uso de indices en oracle



Listar columnas con índices en PostgreSQL (19)

Me gustaría obtener las columnas en las que se encuentra un índice en PostgreSQL.

En MySQL puede usar SHOW INDEXES FOR table y ver la columna Column_name .

mysql> show indexes from foos; +-------+------------+---------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+ | Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | +-------+------------+---------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+ | foos | 0 | PRIMARY | 1 | id | A | 19710 | NULL | NULL | | BTREE | | | foos | 0 | index_foos_on_email | 1 | email | A | 19710 | NULL | NULL | YES | BTREE | | | foos | 1 | index_foos_on_name | 1 | name | A | 19710 | NULL | NULL | | BTREE | | +-------+------------+---------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+

¿Existe algo como esto para PostgreSQL?

Lo he intentado en el psql comando psql (con la opción -E para mostrar SQL) pero no muestra la información que estoy buscando.

Actualización: Gracias a todos los que agregaron sus respuestas. cope360 me dio exactamente lo que estaba buscando, pero varias personas intervinieron con enlaces muy útiles. Para referencia futura, consulte la documentación de pg_index (a través de Milen A. Radev ) y el muy útil artículo Extracción de información de META de PostgreSQL (a través de Michał Niklas ).


Similar a la respuesta aceptada, pero al haber dejado join en pg_attribute como join o query normal con pg_attribute, no da índices que son como:
create unique index unique_user_name_index on users (lower(name))

select row_number() over (order by c.relname), c.relname as index, t.relname as table, array_to_string(array_agg(a.attname), '', '') as column_names from pg_class c join pg_index i on c.oid = i.indexrelid and c.relkind=''i'' and c.relname not like ''pg_%'' join pg_class t on t.oid = i.indrelid left join pg_attribute a on a.attrelid = t.oid and a.attnum = ANY(i.indkey) group by t.relname, c.relname order by c.relname;


# /di

La manera más fácil y más corta es /di , que listará todos los índices en la base de datos actual.

$ /di List of relations Schema | Name | Type | Owner | Table --------+-----------------------------+-------+----------+--------------- public | part_delivery_index | index | shipper | part_delivery public | part_delivery_pkey | index | shipper | part_delivery public | shipment_by_mandator | index | shipper | shipment_info public | shipment_by_number_and_size | index | shipper | shipment_info public | shipment_info_pkey | index | shipper | shipment_info (5 rows)

/di es el "hermano pequeño" del comando /d que enumerará todas las relaciones de la base de datos actual. Por lo tanto, /di ciertamente significa "muéstrame esta d atabases i ndex".

Typing /diS mostrará una lista de todos los índices utilizados en todo el sistema, lo que significa que también obtendrá todos los índices pg_catalog.

$ /diS List of relations Schema | Name | Type | Owner | Table ------------+-------------------------------------------+-------+----------+------------------------- pg_catalog | pg_aggregate_fnoid_index | index | postgres | pg_aggregate pg_catalog | pg_am_name_index | index | postgres | pg_am pg_catalog | pg_am_oid_index | index | postgres | pg_am pg_catalog | pg_amop_fam_strat_index | index | postgres | pg_amop pg_catalog | pg_amop_oid_index | index | postgres | pg_amop pg_catalog | pg_amop_opr_fam_index | index | postgres | pg_amop pg_catalog | pg_amproc_fam_proc_index | index | postgres | pg_amproc pg_catalog | pg_amproc_oid_index | index | postgres | pg_amproc pg_catalog | pg_attrdef_adrelid_adnum_index | index | postgres | pg_attrdef --More--

Con estos dos comandos, puede agregar un + después para obtener incluso más información, como el tamaño del espacio en disco que necesita el índice y una descripción, si está disponible.

$ /di+ List of relations Schema | Name | Type | Owner | Table | Size | Description --------+-----------------------------+-------+----------+---------------+-------+------------- public | part_delivery_index | index | shipper | part_delivery | 16 kB | public | part_delivery_pkey | index | shipper | part_delivery | 16 kB | public | shipment_by_mandator | index | shipper | shipment_info | 19 MB | public | shipment_by_number_and_size | index | shipper | shipment_info | 19 MB | public | shipment_info_pkey | index | shipper | shipment_info | 53 MB | (5 rows)

En psql puede encontrar ayuda fácilmente sobre los comandos que escriben /? .


¿Qué tal una solución simple?

SELECT t.relname table_name, ix.relname index_name, indisunique, indisprimary, regexp_replace(pg_get_indexdef(indexrelid), ''.*/((.*)/)'', ''/1'') columns FROM pg_index i JOIN pg_class t ON t.oid = i.indrelid JOIN pg_class ix ON ix.oid = i.indexrelid WHERE t.relname LIKE ''test%''

`


Algunos datos de muestra ...

create table test (a int, b int, c int, constraint pk_test primary key(a, b)); create table test2 (a int, b int, c int, constraint uk_test2 unique (b, c)); create table test3 (a int, b int, c int, constraint uk_test3b unique (b), constraint uk_test3c unique (c), constraint uk_test3ab unique (a, b));

Use la función pg_get_indexdef :

select pg_get_indexdef(indexrelid) from pg_index where indrelid = ''test''::regclass; pg_get_indexdef -------------------------------------------------------- CREATE UNIQUE INDEX pk_test ON test USING btree (a, b) (1 row) select pg_get_indexdef(indexrelid) from pg_index where indrelid = ''test2''::regclass; pg_get_indexdef ---------------------------------------------------------- CREATE UNIQUE INDEX uk_test2 ON test2 USING btree (b, c) (1 row) select pg_get_indexdef(indexrelid) from pg_index where indrelid =''test3''::regclass; pg_get_indexdef ------------------------------------------------------------ CREATE UNIQUE INDEX uk_test3b ON test3 USING btree (b) CREATE UNIQUE INDEX uk_test3c ON test3 USING btree (c) CREATE UNIQUE INDEX uk_test3ab ON test3 USING btree (a, b) (3 rows)


Aquí hay una función que envuelve la respuesta de cope360:

CREATE OR REPLACE FUNCTION getIndices(_table_name varchar) RETURNS TABLE(table_name varchar, index_name varchar, column_name varchar) AS $$ BEGIN RETURN QUERY select t.relname::varchar as table_name, i.relname::varchar as index_name, a.attname::varchar as column_name from pg_class t, pg_class i, pg_index ix, pg_attribute a where t.oid = ix.indrelid and i.oid = ix.indexrelid and a.attrelid = t.oid and a.attnum = ANY(ix.indkey) and t.relkind = ''r'' and t.relname = _table_name order by t.relname, i.relname; END; $$ LANGUAGE plpgsql;

Uso:

select * from getIndices(''<my_table>'')


Buena respuesta de @cope360, convertida para usar la sintaxis de unión.

select t.relname as table_name , i.relname as index_name , array_to_string(array_agg(a.attname), '', '') as column_names from pg_class t join pg_index ix on t.oid = ix.indrelid join pg_class i on i.oid = ix.indexrelid join pg_attribute a on a.attrelid = t.oid and a.attnum = ANY(ix.indkey) where t.relkind = ''r'' and t.relname like ''test%'' group by t.relname , i.relname order by t.relname , i.relname ;


Combinado con código de otros y creado una vista:

CREATE OR REPLACE VIEW view_index AS SELECT n.nspname as "schema" ,t.relname as "table" ,c.relname as "index" ,pg_get_indexdef(indexrelid) as "def" FROM pg_catalog.pg_class c JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace JOIN pg_catalog.pg_index i ON i.indexrelid = c.oid JOIN pg_catalog.pg_class t ON i.indrelid = t.oid WHERE c.relkind = ''i'' and n.nspname not in (''pg_catalog'', ''pg_toast'') and pg_catalog.pg_table_is_visible(c.oid) ORDER BY n.nspname ,t.relname ,c.relname;


Crea algunos datos de prueba ...

create table test (a int, b int, c int, constraint pk_test primary key(a, b)); create table test2 (a int, b int, c int, constraint uk_test2 unique (b, c)); create table test3 (a int, b int, c int, constraint uk_test3b unique (b), constraint uk_test3c unique (c),constraint uk_test3ab unique (a, b));

Listar índices y columnas indexadas:

select t.relname as table_name, i.relname as index_name, a.attname as column_name from pg_class t, pg_class i, pg_index ix, pg_attribute a where t.oid = ix.indrelid and i.oid = ix.indexrelid and a.attrelid = t.oid and a.attnum = ANY(ix.indkey) and t.relkind = ''r'' and t.relname like ''test%'' order by t.relname, i.relname; table_name | index_name | column_name ------------+------------+------------- test | pk_test | a test | pk_test | b test2 | uk_test2 | b test2 | uk_test2 | c test3 | uk_test3ab | a test3 | uk_test3ab | b test3 | uk_test3b | b test3 | uk_test3c | c

Enrolle los nombres de las columnas:

select t.relname as table_name, i.relname as index_name, array_to_string(array_agg(a.attname), '', '') as column_names from pg_class t, pg_class i, pg_index ix, pg_attribute a where t.oid = ix.indrelid and i.oid = ix.indexrelid and a.attrelid = t.oid and a.attnum = ANY(ix.indkey) and t.relkind = ''r'' and t.relname like ''test%'' group by t.relname, i.relname order by t.relname, i.relname; table_name | index_name | column_names ------------+------------+-------------- test | pk_test | a, b test2 | uk_test2 | b, c test3 | uk_test3ab | a, b test3 | uk_test3b | b test3 | uk_test3c | c


Cuando se juega con índices, el orden en que se construyen las columnas en el índice es tan importante como las propias columnas.

La siguiente consulta enumera todos los índices de una tabla determinada y todas sus columnas de forma ordenada.

SELECT table_name, index_name, string_agg(column_name, '','') FROM ( SELECT t.relname AS table_name, i.relname AS index_name, a.attname AS column_name, (SELECT i FROM (SELECT *, row_number() OVER () i FROM unnest(indkey) WITH ORDINALITY AS a(v)) a WHERE v = attnum) FROM pg_class t, pg_class i, pg_index ix, pg_attribute a WHERE t.oid = ix.indrelid AND i.oid = ix.indexrelid AND a.attrelid = t.oid AND a.attnum = ANY (ix.indkey) AND t.relkind = ''r'' AND t.relname LIKE ''tablename'' ORDER BY table_name, index_name, i ) raw GROUP BY table_name, index_name


Este comando muestra la vista de las tablas variables, índices y restricciones también

=# /d table_name;

Ejemplo:

testannie=# /d dv.l_customer_account;


La información sin procesar está en pg_index .


No creo que esta versión exista aún en este hilo: proporciona tanto la lista de nombres de columna junto con el ddl para el índice.

CREATE OR REPLACE VIEW V_TABLE_INDEXES AS SELECT n.nspname as "schema" ,t.relname as "table" ,c.relname as "index" ,i.indisunique AS "is_unique" ,array_to_string(array_agg(a.attname), '', '') as "columns" ,pg_get_indexdef(i.indexrelid) as "ddl" FROM pg_catalog.pg_class c JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace JOIN pg_catalog.pg_index i ON i.indexrelid = c.oid JOIN pg_catalog.pg_class t ON i.indrelid = t.oid JOIN pg_attribute a ON a.attrelid = t.oid AND a.attnum = ANY(i.indkey) WHERE c.relkind = ''i'' and n.nspname not in (''pg_catalog'', ''pg_toast'') and pg_catalog.pg_table_is_visible(c.oid) GROUP BY n.nspname ,t.relname ,c.relname ,i.indisunique ,i.indexrelid ORDER BY n.nspname ,t.relname ,c.relname;

Descubrí que los índices que usan funciones no se vinculan con los nombres de las columnas, por lo que ocasionalmente se encuentra una lista de índices, por ejemplo, un nombre de columna cuando en realidad se usa 3.

Ejemplo:

CREATE INDEX ui1 ON table1 (coalesce(col1,''''),coalesce(col2,''''),col3)

La consulta devuelve solo ''col3'' como una columna en el índice, pero el DDL muestra el conjunto completo de columnas utilizadas en el índice.


Por favor, intente la consulta a continuación para profundizar en los índices requeridos

Consulta de la siguiente manera: lo he intentado personalmente y lo uso con frecuencia.

SELECT n.nspname as "Schema", c.relname as "Name", CASE c.relkind WHEN ''r'' THEN ''table'' WHEN ''v'' THEN ''view'' WHEN ''i'' THEN ''index'' WHEN ''S'' THEN ''sequence'' WHEN ''s'' THEN ''special'' END as "Type", u.usename as "Owner", c2.relname as "Table" FROM pg_catalog.pg_class c JOIN pg_catalog.pg_index i ON i.indexrelid = c.oid JOIN pg_catalog.pg_class c2 ON i.indrelid = c2.oid LEFT JOIN pg_catalog.pg_user u ON u.usesysid = c.relowner LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace WHERE c.relkind IN (''i'','''') AND n.nspname NOT IN (''pg_catalog'', ''pg_toast'') AND pg_catalog.pg_table_is_visible(c.oid) AND c2.relname like ''%agg_transaction%'' --table name AND nspname = ''edjus'' -- schema name ORDER BY 1,2;


RESULTADO DE LA CONSULTA:

table | column | type | notnull | index_name | is_index | primarykey | uniquekey | default -------+----------------+------------------------+---------+--------------+----------+- -----------+-----------+--------- nodes | dns_datacenter | character varying(255) | f | | f | f | f | nodes | dns_name | character varying(255) | f | dns_name_idx | t | f | f | nodes | id | uuid | t | nodes_pkey | t | t | t | (3 rows)

CONSULTA:

SELECT c.relname AS table, f.attname AS column, pg_catalog.format_type(f.atttypid,f.atttypmod) AS type, f.attnotnull AS notnull, i.relname as index_name, CASE WHEN i.oid<>0 THEN ''t'' ELSE ''f'' END AS is_index, CASE WHEN p.contype = ''p'' THEN ''t'' ELSE ''f'' END AS primarykey, CASE WHEN p.contype = ''u'' THEN ''t'' WHEN p.contype = ''p'' THEN ''t'' ELSE ''f'' END AS uniquekey, CASE WHEN f.atthasdef = ''t'' THEN d.adsrc END AS default FROM pg_attribute f JOIN pg_class c ON c.oid = f.attrelid JOIN pg_type t ON t.oid = f.atttypid LEFT JOIN pg_attrdef d ON d.adrelid = c.oid AND d.adnum = f.attnum LEFT JOIN pg_namespace n ON n.oid = c.relnamespace LEFT JOIN pg_constraint p ON p.conrelid = c.oid AND f.attnum = ANY (p.conkey) LEFT JOIN pg_class AS g ON p.confrelid = g.oid LEFT JOIN pg_index AS ix ON f.attnum = ANY(ix.indkey) and c.oid = f.attrelid and c.oid = ix.indrelid LEFT JOIN pg_class AS i ON ix.indexrelid = i.oid WHERE c.relkind = ''r''::char AND n.nspname = ''public'' -- Replace with Schema name --AND c.relname = ''nodes'' -- Replace with table name, or Comment this for get all tables AND f.attnum > 0 ORDER BY c.relname,f.attname;


Si desea conservar el orden de las columnas en el índice, esta es una forma (muy fea) de hacerlo:

select table_name, index_name, array_agg(column_name) from ( select t.relname as table_name, i.relname as index_name, a.attname as column_name, unnest(ix.indkey) as unn, a.attnum from pg_class t, pg_class i, pg_index ix, pg_attribute a where t.oid = ix.indrelid and i.oid = ix.indexrelid and a.attrelid = t.oid and a.attnum = ANY(ix.indkey) and t.relkind = ''r'' and t.relnamespace = <oid of the schema you''re interested in> order by t.relname, i.relname, generate_subscripts(ix.indkey,1)) sb where unn = attnum group by table_name, index_name

el orden de las columnas se almacena en la columna pg_index.indkey, por lo que solicité los subíndices de esa matriz.


Solo hazlo: /d table_name

Pero no estoy seguro de qué quiere decir que la información sobre las columnas no está allí.

Por ejemplo:

# /d pg_class Table "pg_catalog.pg_class" Column | Type | Modifiers -----------------+-----------+----------- relname | name | not null relnamespace | oid | not null reltype | oid | not null reloftype | oid | not null relowner | oid | not null relam | oid | not null relfilenode | oid | not null reltablespace | oid | not null relpages | integer | not null reltuples | real | not null reltoastrelid | oid | not null reltoastidxid | oid | not null relhasindex | boolean | not null relisshared | boolean | not null relistemp | boolean | not null relkind | "char" | not null relnatts | smallint | not null relchecks | smallint | not null relhasoids | boolean | not null relhaspkey | boolean | not null relhasexclusion | boolean | not null relhasrules | boolean | not null relhastriggers | boolean | not null relhassubclass | boolean | not null relfrozenxid | xid | not null relacl | aclitem[] | reloptions | text[] | Indexes: "pg_class_oid_index" UNIQUE, btree (oid) "pg_class_relname_nsp_index" UNIQUE, btree (relname, relnamespace)

Muestra claramente qué columnas dado índice está en esta tabla.



/d tablename muestra los nombres de columna para mí en la versión 8.3.8.

"username_idx" UNIQUE, btree (username), tablespace "alldata1"


PostgreSQL ( pg_indexes ):

SELECT * FROM pg_indexes WHERE tablename = ''mytable'';

MySQL ( MOSTRAR ÍNDICE ):

SHOW INDEX FROM mytable;