Let me show you different ways to create and use GIN indexes with JSONB:

-- 1. Basic GIN index for all keys in JSONB
CREATE INDEX idx_data_gin ON your_table USING GIN (data);

-- 2. GIN index for specific operator
CREATE INDEX idx_data_gin_path_ops ON your_table USING GIN (data jsonb_path_ops);

-- 3. GIN index for specific key
CREATE INDEX idx_specific_key ON your_table USING GIN ((data -> 'specific_key'));

-- 4. GIN index for array elements
CREATE INDEX idx_array_elements ON your_table USING GIN ((data -> 'array_field'));

-- 5. Partial GIN index
CREATE INDEX idx_partial_gin ON your_table USING GIN (data)
WHERE data ? 'important_key';

Example queries that use these indexes:

-- Contains operator ?
SELECT * FROM your_table WHERE data ? 'key_name';

-- Path matching @>
SELECT * FROM your_table
WHERE data @> '{"status": "active", "type": "user"}';

-- Key-value match
SELECT * FROM your_table
WHERE data->>'status' = 'active';

-- Array operations
SELECT * FROM your_table
WHERE data->'tags' ? 'urgent';

-- Complex nested queries
SELECT * FROM your_table
WHERE data @> '{"address": {"city": "New York"}}';

Monitoring index usage:

-- Check if index is being used
EXPLAIN ANALYZE
SELECT * FROM your_table
WHERE data @> '{"status": "active"}';

-- Index size
SELECT pg_size_pretty(pg_relation_size('idx_data_gin'));

-- Index statistics
SELECT * FROM pg_stat_user_indexes
WHERE indexrelname = 'idx_data_gin';

Best practices:

  1. Use jsonb_path_ops when you only need containment (@>) queries
  2. Create specific key indexes for frequently queried keys
  3. Monitor index size - GIN indexes can become large
  4. Drop unused indexes
  5. Consider partial indexes for specific data subsets

Would you like me to explain any specific type of GIN indexing in more detail?