2011-07-21 14 views
47

Co to jest zapytanie, aby uzyskać listę wszystkich nazw indeksów, ich nazwy kolumn i nazwy tabel z bazą danych PostgreSQL?Lista wszystkich nazw indeksów, nazw kolumn i ich nazwa bazy danych PostgreSQL

Próbowałem uzyskać listę wszystkich indeksów w db za pomocą tego zapytania, ale jak uzyskać listę indeksów, nazwy kolumn i nazwy tabel?

SELECT * 
FROM pg_class, pg_index 
WHERE pg_class.oid = pg_index.indexrelid 
AND pg_class.oid IN (
    SELECT indexrelid 
    FROM pg_index, pg_class 
    WHERE pg_class.oid=pg_index.indrelid 
    AND indisunique != 't' 
    AND indisprimary != 't' 
    AND relname !~ '^pg_');` 

Odpowiedz

84

wyjście to wszystkie indeksy ze szczegółami (wyciąg z moim zdaniem definicji):

SELECT i.relname as indname, 
     i.relowner as indowner, 
     idx.indrelid::regclass, 
     am.amname as indam, 
     idx.indkey, 
     ARRAY(
     SELECT pg_get_indexdef(idx.indexrelid, k + 1, true) 
     FROM generate_subscripts(idx.indkey, 1) as k 
     ORDER BY k 
     ) as indkey_names, 
     idx.indexprs IS NOT NULL as indexprs, 
     idx.indpred IS NOT NULL as indpred 
FROM pg_index as idx 
JOIN pg_class as i 
ON  i.oid = idx.indexrelid 
JOIN pg_am as am 
ON  i.relam = am.oid; 

Ewentualnie dodać dodatkowy przyłączyć do końca tak, aby przyciąć nazw:

SELECT i.relname as indname, 
     i.relowner as indowner, 
     idx.indrelid::regclass, 
     am.amname as indam, 
     idx.indkey, 
     ARRAY(
     SELECT pg_get_indexdef(idx.indexrelid, k + 1, true) 
     FROM generate_subscripts(idx.indkey, 1) as k 
     ORDER BY k 
     ) as indkey_names, 
     idx.indexprs IS NOT NULL as indexprs, 
     idx.indpred IS NOT NULL as indpred 
FROM pg_index as idx 
JOIN pg_class as i 
ON  i.oid = idx.indexrelid 
JOIN pg_am as am 
ON  i.relam = am.oid 
JOIN pg_namespace as ns 
ON  ns.oid = i.relnamespace 
AND ns.nspname = ANY(current_schemas(false)); 
+0

świetnie działa; dla mnie potrzebuję tylko zdefiniowanych przez użytkownika indeksów, więc mam inny warunek "GDZIE i.relname! ~ '^ (pg_ | sql _)" – vchitta

+2

Prawdopodobnie nie potrzebujesz tego warunku, jeśli używasz drugiego wysłanego przeze mnie zapytania. Usuwa wszystko, co nie żyje na twojej ścieżce (bez schematów systemowych). –

40

Bardziej przyjazna człowiekowi wersja rozwiązania @Denis:

SELECT 
    U.usename    AS user_name, 
    ns.nspname    AS schema_name, 
    idx.indrelid :: REGCLASS AS table_name, 
    i.relname    AS index_name, 
    idx.indisunique   AS is_unique, 
    idx.indisprimary   AS is_primary, 
    am.amname    AS index_type, 
    idx.indkey, 
     ARRAY(
      SELECT pg_get_indexdef(idx.indexrelid, k + 1, TRUE) 
      FROM 
      generate_subscripts(idx.indkey, 1) AS k 
      ORDER BY k 
     ) AS index_keys, 
    (idx.indexprs IS NOT NULL) OR (idx.indkey::int[] @> array[0]) AS is_functional, 
    idx.indpred IS NOT NULL AS is_partial 
FROM pg_index AS idx 
    JOIN pg_class AS i 
    ON i.oid = idx.indexrelid 
    JOIN pg_am AS am 
    ON i.relam = am.oid 
    JOIN pg_namespace AS NS ON i.relnamespace = NS.OID 
    JOIN pg_user AS U ON i.relowner = U.usesysid 
WHERE NOT nspname LIKE 'pg%'; -- Excluding system tables 
7

Query do listy wszystkie indeksy bazy

SELECT 
    tablename, 
    indexes [1], 
    indexes [2], 
    indexes [3], 
    indexes [4], 
    indexes [5], 
    indexes [6], 
    indexes [7], 
    indexes [8], 
    indexes [9], 
    indexes [10] 
FROM (SELECT 
    tablename, 
    array_agg(indexname) AS indexes 
FROM pg_indexes 
WHERE schemaname = 'public' 
GROUP BY tablename) as sub; 
+5

To jest o wiele prostsze. Moja odmiana: 'WYBIERZ schemaname jako schemat, tablename jako table, indexname jako index FROM pg_indexes WHERE schemaname = 'myschema';' – Chris

+0

Co z tabelami o nieznanej (prawdopodobnie> 10) liczbie indeksów? –

2

Jeśli jesteś również zainteresowany wielkości indeksu, można użyć tej kwerendy z PostgreSQL Wiki.

SELECT 
    t.tablename, 
    indexname, 
    c.reltuples AS num_rows, 
    pg_size_pretty(pg_relation_size(quote_ident(t.tablename)::text)) AS table_size, 
    pg_size_pretty(pg_relation_size(quote_ident(indexrelname)::text)) AS index_size, 
    CASE WHEN indisunique THEN 'Y' 
     ELSE 'N' 
    END AS UNIQUE, 
    idx_scan AS number_of_scans, 
    idx_tup_read AS tuples_read, 
    idx_tup_fetch AS tuples_fetched 
FROM pg_tables t 
LEFT OUTER JOIN pg_class c ON t.tablename=c.relname 
LEFT OUTER JOIN 
    (SELECT c.relname AS ctablename, ipg.relname AS indexname, x.indnatts AS number_of_columns, idx_scan, idx_tup_read, idx_tup_fetch, indexrelname, indisunique FROM pg_index x 
      JOIN pg_class c ON c.oid = x.indrelid 
      JOIN pg_class ipg ON ipg.oid = x.indexrelid 
      JOIN pg_stat_all_indexes psai ON x.indexrelid = psai.indexrelid) 
    AS foo 
    ON t.tablename = foo.ctablename 
WHERE t.schemaname='public' 
ORDER BY 1,2; 
1

Oto wersja, która upraszcza rzeczy w porównaniu do innych odpowiedzi według

  • unikając zagnieżdżonych wybiera
  • unikanie funkcji wbudowanych (może być trudne do zapamiętania)
  • pomocą świetnych LATERAL i UNNEST(...) WITH ORDINALITY funkcje dostępne w późniejszych wersjach PostgreSQL (9.4+)
SELECT 
    tnsp.nspname AS schema_name, 
    trel.relname AS table_name, 
    irel.relname AS index_name, 
    array_agg (a.attname ORDER BY c.ordinality) AS columns 
FROM pg_index AS i 
JOIN pg_class AS trel ON trel.oid = i.indrelid 
JOIN pg_namespace AS tnsp ON trel.relnamespace = tnsp.oid 
JOIN pg_class AS irel ON irel.oid = i.indexrelid 
CROSS JOIN LATERAL unnest (i.indkey) WITH ORDINALITY AS c (colnum, ordinality) 
JOIN pg_attribute AS a ON trel.oid = a.attrelid AND a.attnum = c.colnum 
GROUP BY tnsp.nspname, trel.relname, irel.relname 
Powiązane problemy