PostgreSQL
 sql >> Base de Dados >  >> RDS >> PostgreSQL

Representando dados esparsos no PostgreSQL


Suponho que você esteja pensando em matrizes esparsas do contexto matemático:http://en.wikipedia. org/wiki/Sparse_matrix (As técnicas de armazenamento descritas são para armazenamento de memória (operação aritmética rápida), não para armazenamento persistente (baixo uso de disco).)

Como geralmente se opera nessas matrizes no lado do cliente, e não no lado do servidor, um SQL-ARRAY[] é a melhor escolha!

A questão é como aproveitar a escassez da matriz? Aqui os resultados de algumas investigações.

Configurar:
  • Postgres 8.4
  • Matrizes com 400*400 elementos em precisão dupla (8 bytes) --> tamanho bruto de 1,28 MiB por matriz
  • 33% de elementos diferentes de zero --> 427 kiB de tamanho efetivo por matriz
  • média usando aproximadamente 1.000 matrizes aleatórias diferentes

Métodos concorrentes:
  • Confie no automático lado do servidor compressão de colunas com SET STORAGE MAIN ou EXTENDED.
  • Armazene apenas os elementos diferentes de zero mais um bitmap (bit varying(xx) ) descrevendo onde localizar os elementos diferentes de zero na matriz. (Uma precisão dupla é 64 vezes maior que um bit. Em teoria (ignorando as sobrecargas), esse método deve ser uma melhoria se <=98% for diferente de zero;-).) A compactação do lado do servidor está ativada.
  • Substituir os zeros na matriz com NULL . (Os RDBMSs são muito eficazes no armazenamento de NULLs.) A compactação do lado do servidor é ativada.

(A indexação de elementos diferentes de zero usando um 2º índice-ARRAY[] não é muito promissora e, portanto, não foi testada.)

Resultados:
  • Compressão automática
    • sem esforços extras de implementação
    • sem tráfego de rede reduzido
    • sobrecarga mínima de compactação
    • armazenamento persistente =39% do tamanho bruto
  • Bitmap
    • esforço de implementação aceitável
    • tráfego de rede ligeiramente diminuído; dependente da escassez
    • armazenamento persistente =33,9% do tamanho bruto
  • Substituir zeros por NULLs
    • algum esforço de implementação (a API precisa saber onde e como definir os NULLs no ARRAY[] enquanto constrói a consulta INSERT)
    • nenhuma alteração no tráfego de rede
    • armazenamento persistente =35% do tamanho bruto

Conclusão:Comece com o parâmetro de armazenamento EXTENDED/MAIN. Se você tiver algum tempo livre, investigue seus dados e use minha configuração de teste com seu nível de dispersão. Mas o efeito pode ser menor do que você espera.

Sugiro sempre usar a serialização da matriz (por exemplo, ordem de linha principal) mais duas colunas inteiras para as dimensões da matriz NxM. Como a maioria das APIs usa SQL textual, você economiza muito tráfego de rede e memória do cliente para "ARRAY[ARRAY[..], ARRAY[..], ARRAY[..], ARRAY[..], ..]" aninhados. !!!

Tebas
CREATE TABLE _testschema.matrix_dense
(
  matdata double precision[]
);
ALTER TABLE _testschema.matrix_dense ALTER COLUMN matdata SET STORAGE EXTERN;


CREATE TABLE _testschema.matrix_sparse_autocompressed
(
  matdata double precision[]
);

CREATE TABLE _testschema.matrix_sparse_bitmap
(
  matdata double precision[]
  bitmap bit varying(8000000)
);

Insira as mesmas matrizes em todas as tabelas. Os dados concretos dependem de determinada tabela. Não altere os dados no lado do servidor devido a páginas não utilizadas, mas alocadas. Ou faça um VÁCUO.
SELECT 
pg_total_relation_size('_testschema.matrix_dense') AS dense, 
pg_total_relation_size('_testschema.matrix_sparse_autocompressed') AS autocompressed, 
pg_total_relation_size('_testschema.matrix_sparse_bitmap') AS bitmap;