Tengo dos mesas left2
y right2
. Ambas tablas serán grandes (de 1 a 10 millones de filas).
CREATE TABLE left2(id INTEGER, t1 INTEGER, d INTEGER);
ALTER TABLE left2 ADD PRIMARY KEY (id,t1);
CREATE TABLE right2( t1 INTEGER, d INTEGER, arr INTEGER[] );
ALTER TABLE right2 ADD PRIMARY KEY(t1,d);
Realizaré este tipo de consulta:
SELECT l.d + r.d,
UNIQ(SORT((array_agg_mult(r.arr)))
FROM left2 l,
right2 r
WHERE l.t1 = r.t1
GROUP BY l.d + r.d
ORDER BY l.d + r.d;
Donde para la agregación de matrices uso la función:
CREATE AGGREGATE array_agg_mult(anyarray) (
SFUNC=array_cat,
STYPE=anyarray,
INITCOND='{}');
Después de concatenar las matrices, uso la UNIQ
función del intarray
módulo. ¿Hay una manera más eficiente de hacer esto? ¿Hay algún índice en el arr
campo para acelerar la fusión (con la eliminación de duplicados)? ¿Puede la función agregada eliminar duplicados directamente? Las matrices originales pueden considerarse ordenadas (y son únicas) si eso ayuda.
El Fiddle de SQL está aquí :
postgresql
postgresql-9.3
aggregate
array
Alexandros
fuente
fuente
right2.arr
ser NULL como sugiere su esquema de demostración? ¿Necesita arreglos ordenados como resultado?Respuestas:
Resultados correctos?
Primero: corrección. ¿Quieres producir una variedad de elementos únicos? Su consulta actual no hace eso. La función
uniq()
del módulo intarray solo promete:Como se indica en el manual , necesitaría:
También le da arreglos ordenados , suponiendo que quiera eso, no lo aclaró.
Veo que tienes
sort()
en tu violín , por lo que esto puede ser un error tipográfico en tu pregunta.Postgres 9.5
De cualquier manera, te encantará el nuevo Postgres 9.5 (actualmente beta). Proporciona las capacidades
array_agg_mult()
listas para usar y mucho más rápido:También ha habido otras mejoras de rendimiento para el manejo de matrices.
Consulta
El propósito principal de
array_agg_mult()
es agregar matrices multidimensionales, pero de todos modos solo se producen matrices unidimensionales. Entonces al menos probaría esta consulta alternativa:Lo que también aborda su pregunta:
Sí, puede, con
DISTINCT
. Pero eso no es más rápido queuniq()
para las matrices de enteros, que se ha optimizado para las matrices de enteros, mientras queDISTINCT
es genérico para todos los tipos de datos que califican.No requiere el
intarray
módulo. Sin embargo , el resultado no está necesariamente ordenado. Postgres utiliza algoritmos variables paraDISTINCT
(IIRC), los conjuntos grandes generalmente se codifican, luego el resultado no se ordena a menos que agregue explícitoORDER BY
. Si necesita matrices ordenadas, puede agregarORDER BY
directamente a la función de agregado:Pero eso suele ser más lento que alimentar datos previamente ordenados
array_agg()
(un tipo grande versus muchos tipos pequeños). Entonces ordenaría una subconsulta y luego agregaría:Esta fue la variante más rápida en mi prueba superficial en Postgres 9.4.
SQL Fiddle basado en el que proporcionó.
Índice
No veo mucho potencial para ningún índice aquí. La única opción sería:
Solo tiene sentido si obtiene escaneos de solo índice de esto, lo que sucederá si la tabla subyacente
right2
es sustancialmente más ancha que solo estas dos columnas y su configuración califica para escaneos de solo índice. Detalles en el Wiki de Postgres.fuente
Estoy realmente decepcionado, esto es algo fácil de hacer en Microsoft Access. Puede crear una consulta "eliminar duplicados" y luego mirar el SQL para ver cómo lo está haciendo. Tendré que encender una máquina Windows para buscar. Varían, el asistente de consultas lo hace.
Creo que una cosa que funciona es cargar todos sus datos en una tabla y luego hacer SELECT DISTINCT en una nueva tabla. También puede seguir un orden por cláusula mientras lo hace. Lo hice de alguna manera hace un año, eso debe ser.
Estoy combinando 2 años de datos de temperatura, el sensor envía 2 copias del mismo punto de datos cada minuto como protección redundante. A veces uno se destroza, pero solo quiero conservar uno. También tengo superposiciones entre archivos.
Si los datos tienen exactamente el mismo formato durante toda la ejecución, en una máquina Unix puede hacer algo como
Pero uniq compara líneas como cadenas y, por ejemplo, 18.7000 no es lo mismo que 18.7. Cambié mi software durante los 2 años, así que tengo ambos formatos.
fuente