Eu sou o DBA (não oficial) responsável por um OODBMS proprietário. A gerência quer que mudemos para o Postgres, para reduzir os custos de licença. O movimento deve ser progressivo, portanto, devemos manter a mesma estrutura de dados do OODBMS. Felizmente, com o suporte para ARRAYs e herança de tabelas, podemos literalmente criar um esquema idêntico no Postgres. Todas as tabelas usarão bigint como chave primária e todas (indiretamente) herdarão da mesma tabela base.
O maior problema é este: nossa chave bigint é (e deve ser) única em todas as tabelas, e devemos ser capazes de carregar rapidamente um conjunto de linhas, com base em sua chave primária, sem saber em qual tabela elas estão . As linhas serão espalhadas por toda e qualquer tabela. A principal preocupação aqui é a velocidade , em vez do uso de disco ou memória.
Expresso de forma diferente, o que precisamos é de um índice exclusivo em todas as tabelas. AFAIK, isso não é possível no Postgres. Qual é a opção "próxima melhor"? Estou aberto a qualquer solução, incluindo usar, ou talvez até codificar, alguma "extensão Postgres".
Para dar algumas dicas sobre o banco de dados real, estamos falando de 300 tabelas, 130 milhões de linhas e cerca de 300 GB de tamanho (tamanho OODBMS).
Não tenho certeza se gosto disso "todas as tabelas herdam da tabela base", mas, considerando isso, parece factível com o Postgres:
Para gerar a chave primária para todas as tabelas, crie uma sequência:
Crie a tabela base usando essa sequência para gerar os valores:
Observe que a chave primária não será aplicada para as tabelas filhas!
Em seguida, crie as tabelas filhas:
Se você agora inserir nas tabelas filhas, a sequência será usada para gerar o ID:
Para descobrir em qual tabela uma linha está localizada, selecione na tabela base e inclua a
tableoid
coluna que identifica a tabela real na qual a linha está localizada:Você ainda precisará de outra consulta para retornar a linha completa da tabela filha.
Exemplo online: https://dbfiddle.uk/?rdbms=postgres_11&fiddle=4305e86b996e7a94c24faed733257232
Outra abordagem que não precisa de herança é gerar valores de ID que codificam o nome da tabela (shudder).
Algo na linha:
Ao multiplicar o valor da sequência por 1000, temos essencialmente os 3 dígitos inferiores disponíveis para codificar um número único para cada tabela. Para poder pesquisar esses números, precisamos dessa tabela adicional.
Observe que isso falhará miseravelmente se a tabela de pesquisa não contiver todas as tabelas!
Então, em vez de usar
nextval()
use, aget_id()
função:Então você pode fazer:
Assim, as linhas em t2 agora vão para os IDs 2003 e 4003. A função
get_tablename()
pode ser usada para recuperar o nome da tabela à qual um ID pertence:Isso é certamente mais rápido em termos de procurar o nome da tabela e não carrega a bagagem de uma enorme árvore de herança. Portanto, em termos de desempenho, provavelmente é mais rápido. No entanto, tornar-se-á um pesadelo de manutenção.
O preenchimento da tabela de pesquisa talvez possa ser feito por meio de acionadores de eventos sempre que uma tabela for criada ou descartada.
Se você puder alterar seu aplicativo para oferecer suporte a chaves primárias varchar, em vez de bigint (e puder conviver com os requisitos de armazenamento um pouco mais altos), também poderá gerar o ID como uma string que simplesmente contém o nome da tabela:
No entanto, coisas como classificação e consultas de intervalo serão complicadas.