AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / dba / Perguntas / 193788
Accepted
Burleigh Bear
Burleigh Bear
Asked: 2017-12-22 16:38:26 +0800 CST2017-12-22 16:38:26 +0800 CST 2017-12-22 16:38:26 +0800 CST

O que pode dar errado usando a mesma sequência em várias tabelas no postgres?

  • 772

Estamos pensando em usar uma sequência compartilhada para atribuir ids a chaves primárias para todas as tabelas em nosso banco de dados. Existem cerca de 100 deles. Apenas alguns são inseridos com frequência e regularidade. Queremos descartar que seja "uma ideia terrível por um motivo óbvio" antes de passarmos para a fase de realmente experimentá-lo e testá-lo em carga.

Nosso pico de carga é da ordem de 1.000 inserções por segundo, em algumas tabelas.

Nossa pesquisa até agora indica que - a velocidade de geração de sequência não deve ser um problema - a fragmentação de sequência (lacunas) acontecerá, mas não deve ser um problema - a exaustão de id não será um problema

Não temos certeza se estamos perdendo outras grandes coisas. Ficaríamos gratos pelas opiniões das pessoas, especialmente de pessoas que tentaram antes e tiveram experiências positivas ou negativas.

Por contexto - temos duas motivações principais para fazer isso.

Uma motivação para fazer isso é para que possamos definir um monte de dicionários (nós os chamamos de escopos) e ter palavras legíveis para humanos atribuídas a esses ids, então queremos ter certeza de que ids em tabelas diferentes nunca se sobreponham. Assim, em um escopo, id 12345 pode receber o valor "Green" e em outro pode ser atribuído "Verde". (Na verdade, não o usamos para internacionalização, mas podemos um dia).

A outra motivação é tornar mais fácil ter várias implantações no campo e saber (definindo exclusivamente a sequência de cada par de dígitos mais significativos) que nossas implantações não sobreporão as chaves primárias. (Como um GUID lite).

postgresql sequence
  • 4 4 respostas
  • 6502 Views

4 respostas

  • Voted
  1. Best Answer
    David Spillett
    2017-12-22T20:09:15+08:002017-12-22T20:09:15+08:00

    Três possíveis questões que vêm à mente são:

    1. Com qualquer recurso compartilhado, você está criando um gargalo em potencial. Meu instinto diz que, para o seu pico de carga, isso não deve ser um problema, mas sugiro fortemente comparar qualquer solução desse tipo em um ambiente de produção semelhante à produção para ter certeza.

    2. Você está essencialmente atribuindo significado a chaves substitutas que anulam parte de seu propósito na teoria RDB. Uma chave substituta por sua natureza não deve ter significado além de ser uma chave para identificar tuplas nessa relação. Se as entidades podem ter significado juntas e, portanto, precisam de chaves livres de colisão, é correto que elas estejam sendo modeladas separadamente ou algo foi perdido nos requisitos e/ou no design do modelo de dados?

    3. Você está introduzindo um ponto potencial de falha. E se uma implantação não obtiver seu ponto inicial de sequência inicial definido? Você então tem um erro de bloqueio de implantação ou as implantações começam no mesmo local "quebrando" seu recurso. Além disso, o que você fará se em algum lugar no futuro alguém achar que é uma boa ideia ramificar uma implantação (em produção, talvez uma empresa inquilina aliene parte de si mesma e precise separar os dados). E se a semente de alguma forma for redefinida por uma implantação de atualização incorreta ou outra migração? [0]

    Se nenhum desses problemas o preocupa, vá em frente, a ideia não vai quebrar nada IMO. Claro que pode haver maneiras melhores , mesmo que esta não esteja errada em si.


    Quando você diz "UUID-lite" significa que já considerou e descontou os UUIDs. É esse o caso e, em caso afirmativo, existem razões específicas para decidir que não são adequados para este projeto?

    Uma possível razão para não usar UUIDs é a fragmentação do índice, embora o significado disso seja muitas vezes superestimado [1] . A resposta do SQL Server para isso é o "GUID sequencial", que é praticamente equivalente ao que você está sugerindo se descontarmos a atribuição de significado aos valores-chave - talvez o postgres tenha um equivalente a isso? É claro que índices sempre crescentes podem ter seus próprios problemas de desempenho (contenção de última página, estatísticas de índice ficando obsoletas) em algumas cargas de trabalho de alto volume muito específicas [2] .

    Outro argumento comum contra UUIDs é o tamanho da chave: por que usar 16 bytes por valor quando 4 ou 8 serão suficientes? Se a exclusividade for realmente uma propriedade útil, isso geralmente superará significativamente as preocupações com o tamanho da chave. Se o tamanho da chave é uma preocupação, mas você está feliz em usar um INT de 64 bits em vez de precisar manter dentro de 32 bits, você pode usar sua técnica sem adicionar um possível problema de contenção de recursos compartilhados, fazendo sua ideia de chave inteira semeada por tabela [3] usando uma definição de coluna INT IDENTITY(<start>, 1)[4] normal , embora novamente isso esteja adicionando complexidade de implantação (uma pequena quantidade, mas certamente não zero).

    A legibilidade humana às vezes é citada como um problema, mas isso remonta a atribuir significado a chaves substitutas.

    A compressibilidade é uma preocupação menos comum, mas que você pode encontrar. Para praticamente qualquer algoritmo de compactação, os UUIDs provavelmente se parecerão com dados aleatórios (portanto, não compactáveis), a menos que você esteja usando algo como UUIDs sequenciais do SQL Server. Isso pode ser uma preocupação para um conjunto muito grande de links (ou outro bloco de dados) que contém muitos IDs de entidade servidos a um aplicativo em uma rede lenta ou se precisar usar algo como os recursos de compactação de índice do SQL Server, embora ambos sejam importantes estão essencialmente apenas reafirmando a preocupação com o tamanho da chave de uma maneira ligeiramente diferente e os UUIDs sequenciais também podem ajudar aqui.


    [0] isso também pode acontecer para colunas de identidade normais, é claro, mas como você está usando um recurso menos comum, está aumentando a chance de um DBA menos experiente depois de perder o problema, se isso acontecer quando você estiver fazendo algo novo e empolgante em outro lugar!

    [1] Sou um cara do SQL Server, suspeito que o problema potencial seja o mesmo no postgres, mas pelo que sei, pode ter um layout de índice diferente que pode atenuar o efeito.

    [2] Embora, novamente, estes possam ser específicos do SQL Server, especialmente o último dos dois exemplos que listei

    [3] Dois principais bytes: variam por banco de dados, próximos dois: variam por tabela, quatro restantes: os bits de incremento

    [4] Essa é a sintaxe do MS SQL Server, a sintaxe do postgres pode variar, mas você deve ver o que quero dizer e ser capaz de traduzir


    tl; dr: se você estiver reinventando a roda, certifique-se de que todos os designs existentes realmente não são adequados antes de começar a considerar por que um novo pode ou não ser.

    • 9
  2. Evan Carroll
    2017-12-22T16:43:04+08:002017-12-22T16:43:04+08:00

    Estamos pensando em usar uma sequência compartilhada para atribuir ids a chaves primárias para todas as tabelas em nosso banco de dados. Existem cerca de 100 deles. Apenas alguns são inseridos com frequência e regularidade. Queremos descartar que seja "uma ideia terrível por um motivo óbvio" antes de passarmos para a fase de realmente experimentá-lo e testá-lo em carga.

    Essa é uma ideia horrível: descarte-a. Basta usar um GUID/UUID. Por que você descartou essa ideia? No PostgreSQL usamos uuid-ossp,

    uuid_generate_v4()Esta função gera um UUID versão 4, que é derivado inteiramente de números aleatórios.

    Assim,

    CREATE EXTENSION uuid-ossp;
    CREATE TABLE f ( f_id uuid DEFAULT uuid_generate_v4() );
    

    Você faz muitas suposições em sua resposta para que ela seja válida,

    • velocidade "não deve ser um problema"
    • lacunas "não devem ser um problema"
    • a exaustão do ID não vai acontecer

    Você não precisa assumir nada disso. E se você obtiver um DOS no ID criando uma lacuna enorme e empurrando o rollover em um fragmento? Por que não usar a solução da indústria para esse problema? Não está claro que há uma única desvantagem. É provável que todos ganhem. Exceto por alguns bytes de armazenamento.

    • 3
  3. ThatDataGuy
    2018-12-27T06:33:23+08:002018-12-27T06:33:23+08:00

    Eu usei o padrão que você propôs com uma tabela de ID central adicional para a qual todas as outras chaves estrangeiras de IDs. Funcionou em um grande sistema de produção totalmente bem.

    Eu acho que a verdadeira razão para fazer isso é se seus ids tiverem um escopo além do seu banco de dados. Por exemplo, no meu exemplo, esses IDs enumeravam títulos e empresas financeiras exclusivas. Você pode perguntar, por que não criar um conjunto de ids para empresas e um segundo conjunto para títulos, como chaves primárias de autoincremento em cada tabela? Porque queríamos que outros registros de séries temporais se referissem a títulos ou empresas. Portanto, a tabela de séries temporais é chaveada para a tabela de id central.

    Dado o exposto, um GUID / UUID também funcionaria bem. No entanto, esses formatos geralmente têm tamanho de 128 bits, o que pode ter um impacto, pois são usados ​​em quase todos os índices, chaves primárias e chaves estrangeiras no banco de dados, e mitigar seu posicionamento não sequencial no intervalo total de id pode ser complicado, levando para um desempenho de seleção abaixo do ideal. Nosso banco de dados era muito voltado para selecionar o desempenho.

    GUIDs / UUIDs têm uma vantagem, que é que eles são muito mais fáceis de criar processos de geração federados. Ou seja, você pode ter vários processos de geração / atribuição de id em sua empresa sem coordenação, apenas assumindo que eles nunca entrarão em conflito. Se seus únicos processos de geração de id estiverem dentro de seu banco de dados, isso não é uma preocupação, mas vale a pena mencionar.

    Observe que a geração de UUID depende de obter seus endereços MAC exclusivos, portanto, você terá que prestar atenção a isso em um ambiente virtual/contêiner.

    • 2
  4. Jack Douglas
    2018-01-03T09:23:28+08:002018-01-03T09:23:28+08:00

    Uma motivação para fazer isso é para que possamos definir um monte de dicionários (nós os chamamos de escopos) e ter palavras legíveis para humanos atribuídas a esses ids, então queremos ter certeza de que ids em tabelas diferentes nunca se sobreponham. Assim, em um escopo, id 12345 pode receber o valor "Green" e em outro pode ser atribuído "Verde". (Na verdade, não o usamos para internacionalização, mas podemos um dia).

    Por si só, eu não deixaria que isso fosse o motivo de escolher um design peculiar e frágil. Se você seguir o caminho não haverá como aproveitar os recursos do banco de dados para garantir a integridade referencial, por exemplo. Uma maneira normalizada tradicional de alcançar a mesma coisa teria benefícios além do RI:

    create table tab1(tab1_id serial primary key);
    create table tab2(tab2_id serial primary key);
    create table scope(scope_id serial primary key, scope_name text);
    create table scope_tab1(scope_id integer references scope, tab1_id integer references tab1, val text, primary key(scope_id,tab1_id));
    insert into scope(scope_name) values ('English'),('French');
    insert into tab1(tab1_id) select generate_series(1,5);
    insert into tab2(tab2_id) select generate_series(1,5);
    insert into scope_tab1(scope_id,tab1_id,val) values (1,1,'Green'),(2,1,'Verde');
    
    select tab1_id
         , (select val from scope_tab1 where scope_id=1 and tab1_id=tab1.tab1_id) val_s1
         , (select val from scope_tab1 where scope_id=2 and tab1_id=tab1.tab1_id) val_s2
    from tab1;
    
    tab1_id | val_s1 | val_s2
    ------: | :----- | :-----
          1 | Verde | Verde
          2 | nulo    | nulo   
          3 | nulo    | nulo   
          4 | nulo    | nulo   
          5 | nulo    | nulo  
    

    dbfiddle aqui

    A outra motivação é tornar mais fácil ter várias implantações no campo e saber (definindo exclusivamente a sequência de cada par de dígitos mais significativos) que nossas implantações não sobreporão as chaves primárias. (Como um GUID lite).

    Eu sugeriria, como outros fizeram, que usar UUID é muito melhor (ou seja, muito menos propenso a erros) do que inventar um novo UUID-lite.

    No entanto, ainda não acho que seja sua melhor aposta - você não está fragmentando, portanto, não há necessidade real de ter IDs não sobrepostos entre implantações que posso ver nas informações fornecidas. Presumivelmente, você tem outras maneiras de identificar uma implantação em um banco de dados além de examinar os IDs nessas tabelas.

    • 1

relate perguntas

  • Posso ativar o PITR depois que o banco de dados foi usado

  • Práticas recomendadas para executar a replicação atrasada do deslocamento de tempo

  • Os procedimentos armazenados impedem a injeção de SQL?

  • Sequências Biológicas do UniProt no PostgreSQL

  • Qual é a diferença entre a replicação do PostgreSQL 9.0 e o Slony-I?

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    conectar ao servidor PostgreSQL: FATAL: nenhuma entrada pg_hba.conf para o host

    • 12 respostas
  • Marko Smith

    Como fazer a saída do sqlplus aparecer em uma linha?

    • 3 respostas
  • Marko Smith

    Selecione qual tem data máxima ou data mais recente

    • 3 respostas
  • Marko Smith

    Como faço para listar todos os esquemas no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Listar todas as colunas de uma tabela especificada

    • 5 respostas
  • Marko Smith

    Como usar o sqlplus para se conectar a um banco de dados Oracle localizado em outro host sem modificar meu próprio tnsnames.ora

    • 4 respostas
  • Marko Smith

    Como você mysqldump tabela (s) específica (s)?

    • 4 respostas
  • Marko Smith

    Listar os privilégios do banco de dados usando o psql

    • 10 respostas
  • Marko Smith

    Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Como faço para listar todos os bancos de dados e tabelas usando o psql?

    • 7 respostas
  • Martin Hope
    Jin conectar ao servidor PostgreSQL: FATAL: nenhuma entrada pg_hba.conf para o host 2014-12-02 02:54:58 +0800 CST
  • Martin Hope
    Stéphane Como faço para listar todos os esquemas no PostgreSQL? 2013-04-16 11:19:16 +0800 CST
  • Martin Hope
    Mike Walsh Por que o log de transações continua crescendo ou fica sem espaço? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland Listar todas as colunas de uma tabela especificada 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney O MySQL pode realizar consultas razoavelmente em bilhões de linhas? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx Como posso monitorar o andamento de uma importação de um arquivo .sql grande? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison Como você mysqldump tabela (s) específica (s)? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    Jonas Como posso cronometrar consultas SQL usando psql? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas Como faço para listar todos os bancos de dados e tabelas usando o psql? 2011-02-18 00:45:49 +0800 CST

Hot tag

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve