Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

183
Views
Índice único con muchas columnas.

Tengo una tabla OLTP ocupada con 30 columnas y 50 millones de filas y quiero evitar duplicados en ella.
¿Qué enfoque debo tomar?

Hasta ahora se me ocurrieron estos:

  • índice único directo en 30 columnas (suena como un índice lento enorme)
  • algún tipo de índice único calculado de la suma de 30 columnas
  • un hash generado en el lado de la aplicación colocado en una nueva columna 31 con índice único btree

Con este último, siento que habrá muchas molestias para regenerar esa columna hash si cambia un esquema de tabla.

¿Tal vez hay algunos otros enfoques en los que no pensé?

over 4 years ago · Santiago Trujillo
1 answers
Answer question

0

postgres 14

... acaba de salir con una función hash incorporada para registros , que es sustancialmente más barata que mi función personalizada. ¡Especialmente para muchas columnas! Ver:

  • Generar ID de hash para registros en DB

Eso hace que el índice de expresión sea mucho más atractivo que una columna más un índice generado. Por lo que sólo:

 CREATE UNIQUE INDEX tbl_row_uni ON tbl (hash_record_extended(tbl.*,0));

Esto normalmente funciona, también:

 CREATE UNIQUE INDEX tbl_row_uni ON tbl (hash_record_extended(tbl,0));

Pero la primera variante es más segura. En la segunda variante, tbl se resolvería en la columna si existiera una columna con el mismo nombre.

Postgres 13 (respuesta original)

Proporcioné una solución para ese problema exactamente en dba.SE recientemente:

  • ¿Por qué no se activa mi restricción ÚNICA?

Está bastante cerca de tu tercera idea:

Básicamente, un hash generado del lado del servidor muy eficiente colocado como columna 31 con restricción UNIQUE .

 CREATE OR REPLACE FUNCTION public.f_tbl_bighash(col1 text, col2 text, ... , col30 text) RETURNS bigint LANGUAGE sql IMMUTABLE PARALLEL SAFE AS 'SELECT hashtextextended(textin(record_out(($1,$2, ... ,$30))), 0)'; ALTER TABLE tbl ADD COLUMN tbl_bighash bigint NOT NULL GENERATED ALWAYS AS (public.f_tbl_bighash(col1, col2, ... , col30)) STORED -- append column in last position , ADD CONSTRAINT tbl_bighash_uni UNIQUE (tbl_bighash);

La belleza de esto: funciona de manera eficiente sin cambiar nada más. (Excepto, posiblemente, cuando use SELECT * o INSERT INTO sin lista de objetivos o similar).

Y también funciona para valores NULL (tratándolos como iguales).

Tenga cuidado si algún tipo de columna tiene una representación de texto no inmutable. (Como timestamptz ). La solución se prueba con todas las columnas de text .

Si el esquema de la tabla cambia , elimine primero la restricción UNIQUE , vuelva a crear la función y vuelva a crear la columna generada, idealmente con una sola declaración ALTER TABLE , para que no vuelva a escribir la tabla dos veces.

Alternativamente , use un índice de expresión UNIQUE basado en public.f_tbl_bighash() . Mismo efecto. Al revés: no hay columna de tabla adicional. Desventaja: un poco más caro, computacionalmente.

over 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!