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 / 286640
Accepted
ldrg
ldrg
Asked: 2021-03-08 14:41:46 +0800 CST2021-03-08 14:41:46 +0800 CST 2021-03-08 14:41:46 +0800 CST

A ordem de coluna otimizada para uma tabela PostgreSQL sempre tem tipos de comprimento variável no final?

  • 772

Há um post de blog popular e aparentemente oficial chamado On Rocks and Sand sobre como otimizar o tamanho das tabelas PostgreSQL para eliminar o preenchimento interno reordenando o comprimento da coluna. Eles explicam como os tipos de comprimento variável incorrem em algum preenchimento extra se não estiverem no final da tabela:

Isso significa que podemos encadear colunas de comprimento variável o dia todo sem introduzir preenchimento, exceto no limite direito. Conseqüentemente, podemos deduzir que as colunas de comprimento variável não apresentam inchaço, desde que estejam no final de uma listagem de colunas.

E no final do post, resumindo:

Classifique as colunas pelo comprimento do tipo, conforme definido em pg_type.

Existe uma biblioteca que se integra ao ActiveRecord do Ruby para reordenar automaticamente as colunas para reduzir o preenchimento chamado pg_column_byte_packer . Você pode ver o README em que o repositório cita a postagem do blog acima e, em geral, faz a mesma coisa que a postagem do blog descreve.

No entanto, o pg_column_byte_packernão retorna resultados consistentes com a postagem do blog que cita. A postagem do blog é extraída do interno do PostgreSQL, pg_type.typelenque coloca colunas de comprimento variável sempre no final por meio de um alinhamento de -1. pg_column_byte_packerdá-lhes um alinhamento de 3.

pg_column_byte_packertem um comentário explicativo :

    # These types generally have an alignment of 4 (as designated by pg_type
    # having a typalign value of 'i', but they're special in that small values
    # have an optimized storage layout. Beyond the optimized storage layout, though,
    # these small values also are not required to respect the alignment the type
    # would otherwise have. Specifically, values with a size of at most 127 bytes
    # aren't aligned. That 127 byte cap, however, includes an overhead byte to store
    # the length, and so in reality the max is 126 bytes. Interestingly TOASTable
    # values are also treated that way, but we don't have a good way of knowing which
    # values those will be.
    #
    # See: `fill_val()` in src/backend/access/common/heaptuple.c (in the conditional
    # `else if (att->attlen == -1)` branch.
    #
    # When no limit modifier has been applied we don't have a good heuristic for
    # determining which columns are likely to be long or short, so we currently
    # just slot them all after the columns we believe will always be long.

O comentário parece não estar errado, pois as colunas de texto têm um pg_type.typalignde 4, mas também têm um pg_type.typlende -1, que a postagem do blog argumenta que obtém a embalagem mais ideal quando no final da tabela.

Portanto, no caso de uma tabela que tenha uma integercoluna, uma textcoluna e uma smallintcoluna, pg_column_byte_packercolocará as colunas de texto entre as duas. Eles até têm um teste de unidade para afirmar que isso sempre acontece.

Minha pergunta aqui é: qual ordem de colunas realmente é compactada para espaço mínimo? O comentário de pg_column_byte_packerparece não estar errado, pois as colunas de texto têm um pg_type.typalignde 4, mas também têm um pg_type.typlende -1.

postgresql
  • 1 1 respostas
  • 240 Views

1 respostas

  • Voted
  1. Best Answer
    Erwin Brandstetter
    2021-03-08T16:58:55+08:002021-03-08T16:58:55+08:00

    O comentário de pg_column_byte_packerparece não estar errado, pois as colunas de texto têm um pg_type.typalignde 4, mas também têm um pg_type.typlende -1.

    Fiquei intrigado também, quando pesquisei alguns anos atrás. typlen = -1apenas indica varlenaarmazenamento, que nominalmente tem typalign = 'i'(alinhamento de inteiro, precisa começar com deslocamento de 4 bytes). Mas essa não é toda a história. Eventualmente, encontrei a explicação em uma nota no código-fonte:

    Observe também que permitimos que o alinhamento nominal seja violado ao armazenar varlenas "empacotadas"; o mecanismo TOAST cuida de esconder isso da maioria dos códigos.

    Portanto, um varlenadatum < 127 bytes (após a possível compactação) adiciona apenas 1 byte de sobrecarga (significando seu comprimento) e não requer preenchimento de alinhamento "no disco" . (Dificilmente existem "discos" mais nos dias de hoje.)

    Ver:

    • Calculando e economizando espaço no PostgreSQL (onde criei o termo "Column Tetris")

    Respondendo a pergunta do título:

    A ordem de coluna otimizada para uma tabela PostgreSQL sempre tem tipos de comprimento variável no final?

    Verdadeiro. Datums que excedem 127 bytes não podem ser armazenados de forma otimizada e voltam a exigir "alinhamento inteiro". Se não sabemos que uma coluna do tipo varlena ficará abaixo desse limite (na maioria das vezes), não podemos dizer com certeza.

    Além disso, há considerações adicionais para armazenamento otimizado. Com muitas colunas em uma linha, é mais barato calcular os deslocamentos de armazenamento de tupla com NOT NULLcolunas de tamanho fixo primeiro. Colocar as colunas acessadas com frequência primeiro também gera uma pequena vantagem. Tudo isso é ainda mais complicado pelo mecanismo TOAST e acesso index(-only).

    Mas todos esses efeitos são tipicamente minúsculos. E perder 3 bytes para o preenchimento de alinhamento é insignificante em comparação quando uma coluna ocupa 200 bytes. Então, principalmente, não vale a pena. A regra geral cobre a maior parte disso:

    Classifique as colunas pelo alinhamento necessáriotypalign :
    d--> i--> s--> c.
    Mas typlen = -1("varlena") por último (tipicamente), embora formalmente typalign = 'i'.

    O manual:

    c = char alignment, i.e., no alignment needed.
    s = short alignment (2 bytes on most machines).
    i = int alignment (4 bytes on most machines).
    d = double alignment (8 bytes on many machines, but by no means all).
    

    Seu exemplo

    Portanto, no caso de uma tabela que tenha uma integercoluna, uma textcoluna e uma smallintcoluna, pg_column_byte_packercolocará as colunas de texto entre as duas.

    pg_column_byte_packerestá fazendo jus ao seu nome. int--> text--> smallinté o mais apertado possível.

    Para o caso típico de strings curtas, a única decisão relevante é colocar em intprimeiro lugar. smallintpode forçar no máximo 1 byte adicional de preenchimento de alinhamento em deslocamentos de bytes ímpares. Como o espaço da tupla é sempre alocado em múltiplos de 8 bytes, isso nunca pode resultar em uma tupla maior.

    Strings que excedem o limite de 127 bytes no disco (incluindo 1 byte de comprimento inicial), mudam para 4 bytes de comprimento inicial e exigem o integeralinhamento nominal. É aí que colocar textantes smallintpode proteger 8 bytes de forma eficaz. Com comprimento de string aleatório que acontece em 25% dos casos, então 2 bytes em média para tuplas de pelo menos 144 bytes.

    Há isso. Mas colocar o smallintprimeiro normalmente tem pequenas vantagens, e a maioria das textcolunas fica bem abaixo do limite de comprimento.

    A coisa a lembrar é não intercalar múltiplas smallinte textcolunas. Vários deslocamentos podem somar neste caso.

    • 2

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