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 / coding / Perguntas / 77323888
Accepted
rwallace
rwallace
Asked: 2023-10-19 20:47:10 +0800 CST2023-10-19 20:47:10 +0800 CST 2023-10-19 20:47:10 +0800 CST

Por que as enumerações do Postgres ocupam 4 bytes?

  • 772

De acordo com https://www.postgresql.org/docs/current/datatype-enum.html

Um valor enum ocupa quatro bytes no disco.

Esta parece uma escolha estranha. É claro que os rótulos enum são mapeados para números inteiros de tamanho fixo para aumentar a velocidade, mas por que 4 bytes?

Na maioria das vezes, enums são usados ​​apenas para algumas opções; 1 byte seria suficiente.

É compreensível que os designers queiram atender a enumerações ocasionais maiores. Qual é o maior enum já visto na natureza? Posso imaginar um sendo usado, por exemplo, para o código do país. São 249 na última contagem; apenas mais alguns países ultrapassariam 1 byte. Posso ver a razão para torná-lo 2 bytes.

Mas por que 4? Alguém já usou um enum de banco de dados com mais de 65.536 casos? O Postgres realmente funciona com tantos?

database
  • 1 1 respostas
  • 22 Views

1 respostas

  • Voted
  1. Best Answer
    Laurenz Albe
    2023-10-19T21:46:45+08:002023-10-19T21:46:45+08:00

    Nos bastidores, um valor enum é a real, não an integer, e é por isso que ocupa quatro bytes. Veja o catálogo do sistema:

    \d pg_enum
                  Table "pg_catalog.pg_enum"
        Column     │ Type │ Collation │ Nullable │ Default 
    ═══════════════╪══════╪═══════════╪══════════╪═════════
     oid           │ oid  │           │ not null │ 
     enumtypid     │ oid  │           │ not null │ 
     enumsortorder │ real │           │ not null │ 
     enumlabel     │ name │           │ not null │ 
    Indexes:
        "pg_enum_oid_index" PRIMARY KEY, btree (oid)
        "pg_enum_typid_label_index" UNIQUE CONSTRAINT, btree (enumtypid, enumlabel)
        "pg_enum_typid_sortorder_index" UNIQUE CONSTRAINT, btree (enumtypid, enumsortorder)
    

    enumtypidé o OID do tipo de dados (de pg_type), enumsortorderé o valor real armazenado na tabela e enumlabelé o rótulo.

    Para entender por que realé usado, veja este exemplo:

    CREATE TYPE wealth AS ENUM ('poor', 'rich');
    
    SELECT * FROM pg_enum WHERE enumtypid = 'wealth'::regtype;
    
      oid  │ enumtypid │ enumsortorder │ enumlabel 
    ═══════╪═══════════╪═══════════════╪═══════════
     35366 │     35364 │             1 │ poor
     35368 │     35364 │             2 │ rich
    (2 rows)
    

    Até agora, isso não é muito surpreendente.

    ALTER TYPE wealth ADD VALUE 'billionaire';
    
    SELECT * FROM pg_enum WHERE enumtypid = 'wealth'::regtype;
    
      oid  │ enumtypid │ enumsortorder │  enumlabel  
    ═══════╪═══════════╪═══════════════╪═════════════
     35366 │     35364 │             1 │ poor
     35368 │     35364 │             2 │ rich
     35370 │     35364 │             3 │ billionaire
    (3 rows)
    

    Isso também está bem claro.

    ALTER TYPE wealth ADD VALUE 'millionaire' BEFORE 'billionaire';
    
    SELECT * FROM pg_enum WHERE enumtypid = 'wealth'::regtype;
    
      oid  │ enumtypid │ enumsortorder │  enumlabel  
    ═══════╪═══════════╪═══════════════╪═════════════
     35366 │     35364 │             1 │ poor
     35368 │     35364 │             2 │ rich
     35370 │     35364 │             3 │ billionaire
     35371 │     35364 │           2.5 │ millionaire
    (4 rows)
    

    Ah! Desde então 'millionaire' < 'billionaire', sua ordem de classificação deve estar entre 'rich'e 'billionaire'. Com um integer, teríamos que alterar a ordem de classificação 'billionaire'para 4 para abrir espaço para o novo rótulo. Mas isso é impossível, porque o valor interno de 3 pode já estar armazenado em alguma tabela em algum lugar, e certamente não podemos sair por aí reescrevendo todas essas tabelas.

    A resposta óbvia é usar um valor de ponto flutuante, para que possamos interpolar novos valores entre os existentes.

    Temos que "desperdiçar" quatro bytes, porque não existe um tipo de dados de ponto flutuante mais curto. Se você considerar que cada linha da tabela tem uma sobrecarga de 23 bytes e que muitos dos três bytes que você gostaria de salvar podem ser perdidos devido ao preenchimento causado por requisitos de alinhamento, você verá que o desperdício não é tão ruim assim.

    • 1

relate perguntas

  • coletar dados de um mapa interativo do datawrapper

  • Erro do Oracle ao tentar criar uma trigger

  • Como criar corretamente o modelo e o cliente mongo?

  • Como referenciar a chave primária na parte derivada da mesma tabela?

  • Permitir acesso à minha lista do microsoft ou excel no onedrive apenas via powerapps

Sidebar

Stats

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

    destaque o código em HTML usando <font color="#xxx">

    • 2 respostas
  • Marko Smith

    Por que a resolução de sobrecarga prefere std::nullptr_t a uma classe ao passar {}?

    • 1 respostas
  • Marko Smith

    Você pode usar uma lista de inicialização com chaves como argumento de modelo (padrão)?

    • 2 respostas
  • Marko Smith

    Por que as compreensões de lista criam uma função internamente?

    • 1 respostas
  • Marko Smith

    Estou tentando fazer o jogo pacman usando apenas o módulo Turtle Random e Math

    • 1 respostas
  • Marko Smith

    java.lang.NoSuchMethodError: 'void org.openqa.selenium.remote.http.ClientConfig.<init>(java.net.URI, java.time.Duration, java.time.Duratio

    • 3 respostas
  • Marko Smith

    Por que 'char -> int' é promoção, mas 'char -> short' é conversão (mas não promoção)?

    • 4 respostas
  • Marko Smith

    Por que o construtor de uma variável global não é chamado em uma biblioteca?

    • 1 respostas
  • Marko Smith

    Comportamento inconsistente de std::common_reference_with em tuplas. Qual é correto?

    • 1 respostas
  • Marko Smith

    Somente operações bit a bit para std::byte em C++ 17?

    • 1 respostas
  • Martin Hope
    fbrereto Por que a resolução de sobrecarga prefere std::nullptr_t a uma classe ao passar {}? 2023-12-21 00:31:04 +0800 CST
  • Martin Hope
    比尔盖子 Você pode usar uma lista de inicialização com chaves como argumento de modelo (padrão)? 2023-12-17 10:02:06 +0800 CST
  • Martin Hope
    Amir reza Riahi Por que as compreensões de lista criam uma função internamente? 2023-11-16 20:53:19 +0800 CST
  • Martin Hope
    Michael A formato fmt %H:%M:%S sem decimais 2023-11-11 01:13:05 +0800 CST
  • Martin Hope
    God I Hate Python std::views::filter do C++20 não filtrando a visualização corretamente 2023-08-27 18:40:35 +0800 CST
  • Martin Hope
    LiDa Cute Por que 'char -> int' é promoção, mas 'char -> short' é conversão (mas não promoção)? 2023-08-24 20:46:59 +0800 CST
  • Martin Hope
    jabaa Por que o construtor de uma variável global não é chamado em uma biblioteca? 2023-08-18 07:15:20 +0800 CST
  • Martin Hope
    Panagiotis Syskakis Comportamento inconsistente de std::common_reference_with em tuplas. Qual é correto? 2023-08-17 21:24:06 +0800 CST
  • Martin Hope
    Alex Guteniev Por que os compiladores perdem a vetorização aqui? 2023-08-17 18:58:07 +0800 CST
  • Martin Hope
    wimalopaan Somente operações bit a bit para std::byte em C++ 17? 2023-08-17 17:13:58 +0800 CST

Hot tag

python javascript c++ c# java typescript sql reactjs html

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