Question :
We have a table of
id|school_id|parent_ids
where parent_ids
is an array of ids.
If we don’t have the school_id
and only parent_id
to search for, then the query will search through all the table rows in parent_ids
array, there might be thousands of rows, and parent_id
might actually be within just few of them.
Does using IN in query for the array column could be a performance barrier in this case?
EDIT
Here is the dump of table structure:
-- ----------------------------
-- Table structure for schools_messages
-- ----------------------------
DROP TABLE IF EXISTS "public"."schools_messages";
CREATE TABLE "public"."schools_messages" (
"id" int4 NOT NULL DEFAULT nextval('schools_messages_id_seq'::regclass),
"message" jsonb NOT NULL DEFAULT '[]'::jsonb,
"details" jsonb NOT NULL DEFAULT '[]'::jsonb,
"school_id" int4 NOT NULL,
"created_at" timestamp(0),
"updated_at" timestamp(0),
"parents_ids" int4[] DEFAULT ARRAY[]::integer[]
)
;
ALTER TABLE "public"."schools_messages" OWNER TO "prod_schools";
-- ----------------------------
-- Primary Key structure for table schools_messages
-- ----------------------------
ALTER TABLE "public"."schools_messages" ADD CONSTRAINT "schools_messages_pkey" PRIMARY KEY ("id");
-- ----------------------------
-- Foreign Keys structure for table schools_messages
-- ----------------------------
ALTER TABLE "public"."schools_messages" ADD CONSTRAINT "schools_messages_school_id_foreign" FOREIGN KEY ("school_id") REFERENCES "public"."trk_schools" ("id") ON DELETE CASCADE ON UPDATE NO ACTION;
Answer :
I agree with Jack that your schema needs help. But you can still do this. Here we do this with one index lookup, using two core extensions intarray
and btree_gist
CREATE EXTENSION intarray;
CREATE EXTENSION btree_gist;
CREATE INDEX ON public.schools_messages
USING gist(school_id, parents_ids gist__int_ops);
VACUUM ANALYZE public.schools_messages;
SELECT *
FROM public.schools_messages
WHERE school_id = 42
OR parent_id @> ARRAY[42];