Eu tenho duas mesas left2
e right2
. Ambas as tabelas serão grandes (de 1 a 10 milhões de linhas).
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);
Vou executar 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;
Onde para agregação de matrizes eu uso a função:
CREATE AGGREGATE array_agg_mult(anyarray) (
SFUNC=array_cat,
STYPE=anyarray,
INITCOND='{}');
Depois de concatenar as matrizes, eu uso a UNIQ
função do intarray
módulo. Existe uma maneira mais eficiente de fazer isso? Existe algum índice no arr
campo para acelerar a fusão (com a remoção de duplicatas)? A função agregada pode remover duplicatas diretamente? Matrizes originais podem ser consideradas classificadas (e são únicas) se isso ajudar.
O SQL Fiddle está aqui :
postgresql
postgresql-9.3
aggregate
array
Alexandros
fonte
fonte
right2.arr
ser NULL como sugere seu esquema demo? Você precisa de matrizes classificadas como resultado?Respostas:
Resultados corretos?
Primeiro: correção. Deseja produzir uma matriz de elementos únicos? Sua consulta atual não faz isso. A função
uniq()
do módulo intarray promete apenas:Como instruído no manual , você precisaria de:
Também fornece matrizes ordenadas - supondo que você queira isso, você não esclareceu.
Vejo que você tem
sort()
no seu violino , então isso pode ser apenas um erro de digitação na sua pergunta.Postgres 9.5
De qualquer forma, você vai adorar o novo Postgres 9.5 (atualmente beta). Ele fornece os recursos prontos
array_agg_mult()
para uso e muito mais rápido:Também houve outras melhorias de desempenho para manipulação de array.
Inquerir
O principal objetivo de
array_agg_mult()
é agregar matrizes multidimensionais, mas você produz apenas matrizes unidimensionais de qualquer maneira. Então, pelo menos, tentaria esta consulta alternativa:O que também aborda sua pergunta:
Sim, pode, com
DISTINCT
. Mas isso não é mais rápido do queuniq()
para matrizes inteiras, que foi otimizado para matrizes inteiras, enquantoDISTINCT
é genérico para todos os tipos de dados qualificados.Não requer o
intarray
módulo. No entanto , o resultado não é necessariamente classificado. O Postgres usa algoritmos variados paraDISTINCT
(IIRC), grandes conjuntos geralmente são divididos em hash e o resultado não é classificado, a menos que você adicione explícitoORDER BY
. Se você precisar de matrizes classificadas, poderá adicionarORDER BY
diretamente à função agregada:Mas isso normalmente é mais lento do que a alimentação de dados pré-classificados
array_agg()
(uma grande classificação versus muitas pequenas). Então, eu classificaria em uma subconsulta e depois agregaria:Essa foi a variante mais rápida no meu teste superficial no Postgres 9.4.
SQL Fiddle com base no que você forneceu.
Índice
Não vejo muito potencial para nenhum índice aqui. A única opção seria:
Só faz sentido se você conseguir verificações apenas de índice - o que acontecerá se a tabela subjacente
right2
for substancialmente mais ampla do que apenas essas duas colunas e sua instalação se qualificar para verificações apenas de índice. Detalhes no Wiki do Postgres.fonte
Estou muito decepcionado, isso é uma coisa fácil de fazer no Microsoft Access. Você pode criar uma consulta "remover duplicados" e, em seguida, examinar o SQL para ver como ele está fazendo isso. Vou ter que iniciar uma máquina Windows para olhar. Eles variam, o assistente de consulta faz isso.
Acho que uma coisa que funciona é carregar todos os seus dados em uma tabela e, em seguida, SELECT DISTINCT em uma nova tabela. Você também pode manter uma ordem por cláusula enquanto estiver nisso. Eu fiz isso de alguma forma um ano atrás, deve ser isso.
Estou combinando 2 anos de dados de temperatura, o sensor envia 2 cópias do mesmo ponto de dados a cada minuto como uma proteção redundante. Às vezes, alguém fica na lixeira, mas eu só quero ficar com um. Eu também tenho sobreposições entre arquivos.
Se os dados tiverem exatamente o mesmo formato durante toda a execução, em uma máquina unix, você poderá fazer algo como
Mas o uniq compara linhas como strings e, por exemplo, 18.7000 não é o mesmo que 18.7. Eu mudei meu software durante os 2 anos, por isso tenho os dois formatos.
fonte