sql >> Base de Datos >  >> RDS >> PostgreSQL

Índice de PostgreSQL en JSON

Sus otros dos índices no funcionarán simplemente porque ->> el operador devuelve text , mientras que obviamente tienes el jsonb clases de operadores de ginebra en mente. Tenga en cuenta que solo menciona json , pero en realidad necesitas jsonb para capacidades avanzadas de indexación.

Para elaborar la mejor estrategia de indexación, tendría que definir más de cerca qué consultas cubrir. ¿Solo te interesan las vacas? ¿O todos los animales/todas las etiquetas? ¿Qué operadores son posibles? ¿Su documento JSON también incluye claves que no son animales? ¿Qué hacer con esos? ¿Quiere incluir filas en el índice donde las vacas (o lo que sea) no aparecen en absoluto en el documento JSON?

Suponiendo:

  • Solo nos interesan las vacas en el primer nivel de anidación.
  • El valor siempre es un integer válido .
  • No estamos interesados ​​en hileras sin vacas.

Sugiero un índice btree funcional, muy parecido al que ya tiene, pero convierta el valor en integer . Supongo que no querrá que la comparación se evalúe como text (donde '2' es mayor que '1111').

CREATE INDEX animal_index ON farm (((animal ->> 'cow')::int));  -- !

El conjunto extra de paréntesis es necesario para que la abreviatura cast haga que la sintaxis de la expresión de índice no sea ambigua.

Use la misma expresión en sus consultas para que Postgres se dé cuenta de que el índice es aplicable:

SELECT * FROM farm WHERE (animal ->> 'cow')::int > 3;

Si necesita un jsonb más genérico índice, considere:

  • ¿Cuál es el índice adecuado para consultar estructuras en matrices en Postgres jsonb?

Para un conocido, estático, trivial número de animales (como comentaste), sugiero índices parciales como:

CREATE INDEX animal_index ON farm (((animal ->> 'cow')::int))
WHERE (animal ->> 'cow') IS NOT NULL;

CREATE INDEX animal_index ON farm (((animal ->> 'chicken')::int))
WHERE (animal ->> 'chicken') IS NOT NULL;

Etc.

Es posible que deba agregar la condición de índice a la consulta:

SELECT * FROM farm
WHERE (animal ->> 'cow')::int > 3
AND   (animal ->> 'cow') IS NOT NULL; 

Puede parecer redundante, pero puede ser necesario. Prueba con ANALYZE !