I have a products table with an array column tags that contains up to 700 elements.
I want to efficiently search for specific tag names for a given user to be used in a search bar.
Here's my query:
SELECT tags
FROM (
SELECT DISTINCT unnest(tags) AS tags
FROM products
WHERE user_id = :id AND tags IS NOT NULL AND cardinality(tags) > 0
) AS unnested_tags
WHERE tags LIKE '%:search%';
I initially created this index to improve performance:
CREATE INDEX CONCURRENTLY idx_products_user_id_tags
ON products(user_id, tags);
However, I encountered the following error:
ERROR: index row size 3240 exceeds btree version 4 maximum 2704
DETAIL: Index row references tuple (50426,2) in relation "products".
HINT: Values larger than 1/3 of a buffer page cannot be indexed.
Consider a function index of an MD5 hash of the value, or use full text indexing.
Most likely due to the tags size.
To address this, I attempted to create the following partial index, but it didn't work:
CREATE INDEX CONCURRENTLY idx_products_user_id_tags_partial
ON products(user_id, tags)
WHERE array_length(tags, 1) <= 100;
Which Indexing Approach is Best for My Use Case?
Key Points
- Moving tags to a separate table is not feasible at this time.
- Partial matches are needed, but exact matches can be considered if they significantly improve query performance.
- Tag length ranges from 1 to over 700 strings.
- Any tag value can be used greater of equal to 3 characters.
I would appreciate any insights or suggestions!
~, can use its normalised version. If individualtagsmay be long, consider full text search, making that 2 added tables: one withtsvector_opsfor whole multi-word tags, another withgin_trgm_opson distinct words in them, to check for misspelling.WHERE tags LIKE '%:search%'(if it was legal syntax) also returns partial matches. Is that intended? Or do you really filter for exact tag names? Postgres version?SELECT version();Exact table definition (CREATE TABLEstatement) How many rows in your table? Table size? (SELECT pg_relation_size('products');Predominant read / write patterns? Min & max length of your tag names? Can any tag name be used, or is there a set of allowed tags?