7

Estoy creando software de foro personalizado para un sitio que estoy creando, que incluye 2 tablas (que son relevantes para esta pregunta): topics y posts. Una publicación pertenece a un tema y el tema contiene el tema, mientras que cada publicación contiene el cuerpo.¿Índice de tsvector dinámico o en columnas?

Aquí está la estructura de las tablas básicas con las columnas correspondientes a mi pregunta:

CREATE TABLE topics (
    id bigserial NOT NULL, 
    title varchar(128) NOT NULL, 
    created timestamp with time zone NOT NULL default NOW(), 
    updated timestamp with time zone NOT NULL default NOW(), 
    PRIMARY KEY (id) 
); 

CREATE TABLE posts (
    id bigserial NOT NULL, 
    topic_id bigint NOT NULL REFERENCES topics(id) ON DELETE CASCADE, 
    body text NOT NULL, 
    created timestamp with time zone NOT NULL default NOW(), 
    updated timestamp with time zone NOT NULL default NOW(), 
    PRIMARY KEY (id) 
); 

Éstos son mis dos opciones en la construcción de índices de texto completo.

Opción 1: Crear índices de tsvector dinámicos en las columnas del título/cuerpo.

CREATE INDEX topics_title_idx ON topics USING gin(to_tsvector(title)); 
CREATE INDEX posts_body_idx ON posts USING gin(to_tsvector(body)); 

Opción 2: crear columnas adicionales para almacenar los datos de título/cuerpo tsvector-izada, y añadir índices en ellos.

ALTER TABLE topics ADD COLUMN topics_vector tsvector NOT NULL; 
CREATE TRIGGER topics_ins BEFORE INSERT OR UPDATE ON topics FOR EACH ROW EXECUTE PROCEDURE tsvector_update_trigger(title_vector, 'pg_catalog.english', title); 
CREATE INDEX topics_title_idx ON topics USING gin(title_vector); 

ALTER TABLE posts ADD COLUMN posts_vector tsvector NOT NULL; 
CREATE TRIGGER posts_ins BEFORE INSERT OR UPDATE ON posts FOR EACH ROW EXECUTE PROCEDURE tsvector_update_trigger(body_vector, 'pg_catalog.english', body); 
CREATE INDEX posts_body_idx ON posts USING gin(body_vector); 

estoy debatiendo entre los dos desde la opción 1 me va a ahorrar espacio en disco, pero ofrecer búsquedas más lentas, y la opción 2 requerirá espacio adicional en disco al tiempo que proporciona búsquedas más rápidas.

Imaginemos que hay 20 nuevos temas & 100 nuevos mensajes por día. ¿Cuál escogerías? ¿Qué ocurre si la cantidad de temas/publicaciones por día es el doble? ¿Cinco veces eso? ¿Diez veces? ¿Su decisión de uno contra el otro cambia?

Respuesta

4

Usando La opción 1 no hará que sus búsquedas sean más lentas.

El índice GIN se usará independientemente de si ha creado una columna instanciada o una expresión calculada.

sólo tiene que cambiar la sintaxis de consulta:

SELECT * 
FROM posts 
WHERE TO_TSVECTOR('english', title) @@ myquery 

en el primer caso, o

SELECT * 
FROM posts 
WHERE title_vector @@ myquery 

en el segundo caso.

Probablemente pueda ahorrar un poco de tiempo al usar TS_RANK en la columna instanciada.

+0

Hmm, tal vez lo leyó mal algo en el manual de entonces, porque me quedé con la impresión de que sería más rápido para hacer algo como la opción 2. –

+1

Si usted está haciendo operaciones con el 'sí TS_VECTOR', como' TS_RANK' , entonces la opción '2' será más rápida. Si solo usa 'TS_VECTOR' para buscar, el rendimiento será el mismo. La columna persistente ni siquiera será referenciada por el optimizador. – Quassnoi

+0

Bueno saber. Voy a querer ordenar por rango, así que probablemente termine usando la opción 2. ¡Gracias! –

4

Vamos a suponer que hay 20 nuevos temas & 100 nuevos mensajes por día. ¿Cuál elegiría ? ¿Qué sucede si el número de temas/publicaciones de por día es el doble? ¿Cinco veces eso? ¿Diez veces? ¿Su decisión de uno vs. el otro cambia?

Eso es alrededor de 36,000 mensajes al año. No importa Probablemente no importe con diez veces eso, incluso en una máquina barata.

Sin embargo, es posible que desee una tercera tabla que contenga un tsvector explícito que combine el tema y el cuerpo-texto al mismo tiempo. A continuación, puede usar el sistema de ponderación incorporado y ejecutar una búsqueda para proporcionar el tipo de búsqueda que las personas generalmente esperan en los foros, etc. Eso significará escribir activadores personalizados para actualizar su tsvector cuando se cambie cualquiera de las tablas de origen.

2

Normalmente iría con almacenar el tsvector en un campo, porque eso también le dará acceso utilizable a cosas como título() y rango().

Cuestiones relacionadas