web-dev-qa-db-fra.com

Meilleur index pour JSONB à Postgres

Nous avons une table contenant environ 500 000 rangées. La table de base de données est censée atteindre des millions d'enregistrements.

C'est comme ça que la table ressemble à:

CREATE TABLE public.influencers
(
    id integer NOT NULL DEFAULT nextval('influencers_id_seq'::regclass),
    location jsonb,
    gender text COLLATE pg_catalog."default",
    birthdate timestamp without time zone,
    ig jsonb,
    contact_info jsonb,
    created_at timestamp without time zone DEFAULT now(),
    updated_at timestamp without time zone DEFAULT now(),
    categories text[] COLLATE pg_catalog."default",
    search_field text COLLATE pg_catalog."default",
    search_vector tsvector,
    ig_updated_at timestamp without time zone,
    CONSTRAINT influencers_pkey PRIMARY KEY (id),
    CONSTRAINT ig_id_must_exist CHECK (ig ? 'id'::text),
    CONSTRAINT ig_username_must_exist CHECK (ig ? 'username'::text)
)

Et ce sont quelques-unes des requêtes que nous devons effectuer efficacement:

SELECT  "public"."influencers".*
FROM "public"."influencers"
WHERE (ig->'follower_count' IS NOT NULL)
ORDER BY (ig->'follower_count') DESC
LIMIT 9
OFFSET 0

SELECT *
FROM "public"."influencers"
WHERE (ig->'follower_count' >= '5000')
LIMIT 9 

SELECT SUM(CAST(ig ->> 'follower_count' AS integer))
FROM "public"."influencers"
WHERE (ig->'follower_count' >= '5000')
  AND (ig->'follower_count' <= '10000')
  AND (ig->'follower_count' IS NOT NULL)

ig -> follower_count sont des valeurs numériques.

J'ai lu que les indices de gin sont principalement destinés à la recherche d'éléments composites (texte), donc je suppose que le meilleur indice à utiliser serait un BTREE. Cela serait-il correct?

3
borjagvo

Les index gin ne fonctionnent pas avec aucun opérateurs JSONB [~ # ~] sauf [~ # ~] ? ?& ?| @>. Clairement, votre utilisation des opérateurs de comparaison >= et <= ne sont pas sur cette liste. Et tous ces opérateurs qu'il pourrait aider ne sont pas non plus sur la liste (ce qui signifie que l'index ne fera rien) Afaik.

Cela signifie avoir besoin d'opérateurs de comparaison indexés, vous aurez besoin d'une BREEE.

CREATE INDEX ON public.influencers ((ig->'follower_count'));

Tout cela dit, je pense que c'est idiot. Juste mettre follower_count En tant que colonne appropriée sur la table actuelle et profitez des avantages de la performance.

3
Evan Carroll