Find indexed textual columns where the indexing does not consider the possibility of pattern-based search. Such columns do not have an index where the used operator class makes the index suitable for use by queries involving pattern matching expressions.
Notes
The query considers only secondary indexes, i.e., indexes that are non-unique, non-function based, and that do not support any constraint. The query excludes foreign key columns because these are usally not used in pattern-matching queries.
Type
Problem detection (Each row in the result could represent a flaw in the design)
Create an index (instead of the index or in addition to the index) where text, varchar, char columns have the operator class text_pattern_ops, varchar_pattern_ops, or char_pattern_ops, respectively. An example: CREATE INDEX test_index ON test_table (col varchar_pattern_ops);
Data Source
INFORMATION_SCHEMA+system catalog
SQL Query
WITH index_op_class AS (SELECT indexrelid, indrelid, indisunique, op_class, ordin
FROM pg_index, unnest(indclass) with ordinality AS k(op_class, ordin)
WHERE indexprs IS NULL
AND indisunique='f'),
indexes AS (SELECT
n.nspname AS table_schema,
c2.relname AS table_name,
a.attname AS column_name,
c.relname AS index_name,
ordin AS ordinal_position,
opcname AS operator_class
FROM
pg_class AS c INNER JOIN index_op_class AS i ON i.indexrelid = c.oid
INNER JOIN pg_class AS c2 ON i.indrelid = c2.oid
INNER JOIN pg_namespace AS n ON c.relnamespace = n.oid
INNER JOIN pg_authid AS u ON n.nspowner = u.oid
INNER JOIN pg_attribute AS a ON a.attrelid = c.oid AND a.attnum=i.ordin
INNER JOIN pg_opclass AS oc ON i.op_class=oc.oid
WHERE c.relkind = 'i'
AND a.attnum>=1
AND a.attisdropped = FALSE
AND (n.nspname = 'public'
OR u.rolname <> 'postgres')
AND NOT EXISTS (SELECT * FROM pg_catalog.pg_constraint AS o WHERE o.conindid=i.indexrelid)),
fk_columns AS (select target_schema as table_schema, target_table as table_name, a.attname as column_name
from (select
(select nspname from pg_namespace where oid=m.relnamespace) as target_schema,
m.relname as target_table,
m.oid as target_table_oid,
unnest(o.conkey) AS target_col
from pg_constraint o inner join pg_class c on c.oid = o.conrelid
inner join pg_class m on m.oid = o.conrelid
where o.contype='f'
and o.conrelid in (select oid from pg_class c where c.relkind = 'r')) t
inner join pg_attribute a on t.target_col = a.attnum and t.target_table_oid = a.attrelid and a.attisdropped = false),
textual_columns AS (SELECT table_schema, table_name, column_name
FROM INFORMATION_SCHEMA.columns
WHERE data_type IN ('text', 'character','character varying') AND
(table_schema, table_name) IN (SELECT table_schema, table_name
FROM INFORMATION_SCHEMA.tables WHERE table_type='BASE TABLE') AND
table_schema NOT IN (SELECT schema_name
FROM INFORMATION_SCHEMA.schemata
WHERE schema_name<>'public' AND
schema_owner='postgres' AND schema_name IS NOT NULL))
SELECT table_schema, table_name, column_name, index_name, operator_class
FROM indexes AS i
WHERE (table_schema, table_name, column_name) IN (SELECT table_schema, table_name, column_name
FROM textual_columns)
AND (table_schema, table_name, column_name) NOT IN (SELECT table_schema, table_name, column_name
FROM fk_columns)
AND operator_class NOT LIKE '%\_pattern_ops'
AND NOT EXISTS (SELECT *
FROM indexes AS i2
WHERE i.table_schema=i2.table_schema
AND i.table_name=i2.table_name
AND i.column_name=i2.column_name
AND i2.operator_class LIKE '%\_pattern_ops')
ORDER BY table_schema, index_name, ordinal_position;
Collections
This query belongs to the following collections:
Name
Description
Find problems automatically
Queries, that results point to problems in the database. Each query in the collection produces an initial assessment. However, a human reviewer has the final say as to whether there is a problem or not .
Categories
This query is classified under the following categories:
Name
Description
Performance
Queries of this category provide information about indexes in a database.