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 / 23879
Accepted
Joe
Joe
Asked: 2012-09-08 01:39:22 +0800 CST2012-09-08 01:39:22 +0800 CST 2012-09-08 01:39:22 +0800 CST

Medir o tamanho de uma linha da tabela PostgreSQL

  • 772

Eu tenho uma tabela PostgreSQL. select *é muito lento enquanto select idé bom e rápido. Acho que pode ser que o tamanho da linha seja muito grande e esteja demorando para transportar, ou pode ser algum outro fator.

Eu preciso de todos os campos (ou quase todos eles), então selecionar apenas um subconjunto não é uma solução rápida. A seleção dos campos que desejo ainda é lenta.

Aqui está meu esquema de tabela menos os nomes:

integer                  | not null default nextval('core_page_id_seq'::regclass)
character varying(255)   | not null
character varying(64)    | not null
text                     | default '{}'::text
character varying(255)   | 
integer                  | not null default 0
text                     | default '{}'::text
text                     | 
timestamp with time zone | 
integer                  | 
timestamp with time zone | 
integer                  | 

O tamanho do campo de texto pode ser de qualquer tamanho. Mas ainda assim, não mais do que alguns kilobytes na pior das hipóteses.

Perguntas

  1. Existe algo sobre isso que grita 'louco ineficiente'?
  2. Existe uma maneira de medir o tamanho da página na linha de comando do Postgres para me ajudar a depurar isso?
postgresql disk-space
  • 5 5 respostas
  • 124109 Views

5 respostas

  • Voted
  1. Best Answer
    Erwin Brandstetter
    2012-09-09T08:08:53+08:002012-09-09T08:08:53+08:00

    Q2:way to measure page size

    O PostgreSQL fornece várias funções de tamanho de objeto de banco de dados . Empacotei os mais interessantes nesta consulta e adicionei algumas funções de acesso a estatísticas na parte inferior. (O módulo adicional pgstattuple ainda fornece funções mais úteis.)

    Isso vai mostrar que diferentes métodos para medir o "tamanho de uma linha" levam a resultados muito diferentes. Tudo depende do que você quer medir, exatamente.

    Esta consulta requer o Postgres 9.3 ou posterior . Para versões mais antigas, veja abaixo.

    Usando uma VALUESexpressão em uma LATERALsubconsulta , para evitar soletrar cálculos para cada linha.

    Substitua public.tblpor seu nome de tabela opcionalmente qualificado pelo esquema para obter uma visualização compacta das estatísticas de tamanho de linha coletadas. Você pode envolver isso em uma função plpgsql para uso repetido, entregar o nome da tabela como parâmetro e usar EXECUTE...

    SELECT l.metric, l.nr AS bytes
         , CASE WHEN is_size THEN pg_size_pretty(nr) END AS bytes_pretty
         , CASE WHEN is_size THEN nr / NULLIF(x.ct, 0) END AS bytes_per_row
    FROM  (
       SELECT min(tableoid)        AS tbl      -- = 'public.tbl'::regclass::oid
            , count(*)             AS ct
            , sum(length(t::text)) AS txt_len  -- length in characters
       FROM   public.tbl t                     -- provide table name *once*
       ) x
    CROSS  JOIN LATERAL (
       VALUES
         (true , 'core_relation_size'               , pg_relation_size(tbl))
       , (true , 'visibility_map'                   , pg_relation_size(tbl, 'vm'))
       , (true , 'free_space_map'                   , pg_relation_size(tbl, 'fsm'))
       , (true , 'table_size_incl_toast'            , pg_table_size(tbl))
       , (true , 'indexes_size'                     , pg_indexes_size(tbl))
       , (true , 'total_size_incl_toast_and_indexes', pg_total_relation_size(tbl))
       , (true , 'live_rows_in_text_representation' , txt_len)
       , (false, '------------------------------'   , NULL)
       , (false, 'row_count'                        , ct)
       , (false, 'live_tuples'                      , pg_stat_get_live_tuples(tbl))
       , (false, 'dead_tuples'                      , pg_stat_get_dead_tuples(tbl))
       ) l(is_size, metric, nr);

    Resultado:

                  métrica | bytes | bytes_pretty | bytes_per_row
    -----------------------------------+----------+--- -----------+---------------
     core_relation_size | 44138496 | 42MB | 91
     visibilidade_mapa | 0 | 0 bytes | 0
     free_space_map | 32768 | 32kB | 0
     table_size_incl_toast | 44179456 | 42MB | 91
     índices_tamanho | 33128448 | 32MB | 68
     total_size_incl_toast_and_indexes | 77307904 | 74MB | 159
     live_rows_in_text_representation | 29987360 | 29MB | 62
     ------------------------------ | | |
     linha_conta | 483424 | |
     live_tuples | 483424 | |
     dead_tuples | 2677 | |

    Para versões mais antigas ( Postgres 9.2 ou anterior ):

    WITH x AS (
       SELECT count(*)               AS ct
            , sum(length(t::text))   AS txt_len  -- length in characters
            , 'public.tbl'::regclass AS tbl      -- provide table name as string
       FROM   public.tbl t                       -- provide table name as name
       ), y AS (
       SELECT ARRAY [pg_relation_size(tbl)
                   , pg_relation_size(tbl, 'vm')
                   , pg_relation_size(tbl, 'fsm')
                   , pg_table_size(tbl)
                   , pg_indexes_size(tbl)
                   , pg_total_relation_size(tbl)
                   , txt_len
                 ] AS val
            , ARRAY ['core_relation_size'
                   , 'visibility_map'
                   , 'free_space_map'
                   , 'table_size_incl_toast'
                   , 'indexes_size'
                   , 'total_size_incl_toast_and_indexes'
                   , 'live_rows_in_text_representation'
                 ] AS name
       FROM   x
       )
    SELECT unnest(name)                AS metric
         , unnest(val)                 AS bytes
         , pg_size_pretty(unnest(val)) AS bytes_pretty
         , unnest(val) / NULLIF(ct, 0) AS bytes_per_row
    FROM   x, y
    
    UNION ALL SELECT '------------------------------', NULL, NULL, NULL
    UNION ALL SELECT 'row_count', ct, NULL, NULL FROM x
    UNION ALL SELECT 'live_tuples', pg_stat_get_live_tuples(tbl), NULL, NULL FROM x
    UNION ALL SELECT 'dead_tuples', pg_stat_get_dead_tuples(tbl), NULL, NULL FROM x;

    Mesmo resultado.

    Q1:anything inefficient?

    Você pode otimizar a ordem das colunas para economizar alguns bytes por linha, atualmente desperdiçados no preenchimento de alinhamento:

    integer                  | not null default nextval('core_page_id_seq'::regclass)
    integer                  | not null default 0
    character varying(255)   | not null
    character varying(64)    | not null
    text                     | default '{}'::text
    character varying(255)   | 
    text                     | default '{}'::text
    text                     |
    timestamp with time zone |
    timestamp with time zone |
    integer                  |
    integer                  |
    

    Isso economiza entre 8 e 18 bytes por linha. Eu chamo de Coluna Tetris . Ver:

    • Configurando o PostgreSQL para desempenho de leitura
    • Calculando e economizando espaço no PostgreSQL

    Considere também:

    • A pesquisa de índice seria visivelmente mais rápida com char vs varchar quando todos os valores são 36 caracteres
    • 138
  2. Daniel Vérité
    2012-09-08T06:23:02+08:002012-09-08T06:23:02+08:00

    Uma aproximação do tamanho de uma linha, incluindo o conteúdo do TOAST 'ed, é fácil de obter consultando o comprimento da representação TEXT de toda a linha:

    SELECT octet_length(t.*::text) FROM tablename AS t WHERE primary_key=:value;
    

    Esta é uma aproximação do número de bytes que serão recuperados do lado do cliente durante a execução:

    SELECT * FROM tablename WHERE primary_key=:value;
    

    ...assumindo que o chamador da consulta está solicitando resultados em formato de texto, que é o que a maioria dos programas faz (o formato binário é possível, mas não vale a pena na maioria dos casos).

    A mesma técnica pode ser aplicada para localizar as Nlinhas "maiores no texto" de tablename:

    SELECT primary_key, octet_length(t.*::text) FROM tablename AS t
       ORDER BY 2 DESC LIMIT :N;
    
    • 66
  3. Chris Travers
    2012-09-08T04:47:34+08:002012-09-08T04:47:34+08:00

    Existem algumas coisas que podem estar acontecendo. Em geral, duvido que o comprimento seja o problema proximal. Suspeito que, em vez disso, você tenha um problema relacionado ao comprimento.

    Você diz que os campos de texto podem chegar a alguns k. Uma linha não pode ultrapassar 8k no armazenamento principal e é provável que seus campos de texto maiores tenham sido torrados ou movidos do armazenamento principal para um armazenamento estendido em arquivos separados. Isso torna seu armazenamento principal mais rápido (portanto, select id é realmente mais rápido porque menos páginas de disco para acessar), mas select * torna-se mais lento porque há mais E/S aleatória.

    Se os tamanhos totais de linha ainda estiverem bem abaixo de 8k, você pode tentar alterar as configurações de armazenamento. Eu, no entanto, aviso que você pode fazer coisas ruins acontecerem ao inserir um atributo superdimensionado no armazenamento principal, então é melhor não tocar nisso se você não precisar e, se precisar, defina limites apropriados por meio de restrições de verificação. Portanto, o transporte provavelmente não é a única coisa. Pode estar agrupando muitos campos que exigem leituras aleatórias. Grandes números de leituras aleatórias também podem causar faltas de cache, e grandes quantidades de memória necessárias podem exigir que as coisas sejam materializadas em disco e um grande número de linhas largas, se uma junção estiver presente (e houver uma se o TOAST estiver envolvido) pode exigir mais custos juntar padrões, etc.

    A primeira coisa que eu faria é selecionar menos linhas e ver se isso ajuda. Se isso funcionar, você pode tentar adicionar mais RAM ao servidor também, mas eu começaria e veria onde o desempenho começa a cair devido a alterações de plano e falhas de cache primeiro.

    • 16
  4. WhiteFire Sondergaard
    2015-05-01T11:58:19+08:002015-05-01T11:58:19+08:00

    Usando as funções de tamanho de objeto de banco de dados mencionadas acima:

    SELECT primary_key, pg_column_size(tablename.*) FROM tablename;
    

    • 15
  5. FredG
    2020-07-01T06:17:57+08:002020-07-01T06:17:57+08:00

    Se uma média do tamanho das linhas atuais for desejada, você poderá usar pg_column_size:

    SELECT SUM(pg_column_size(table_name.*))/COUNT(*) FROM tablename;
    

    Usando por coluna:

    SELECT SUM(pg_column_size(table_name.column_name))/COUNT(*) FROM tablename;
    
    • 6

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

    Como ver a lista de bancos de dados no Oracle?

    • 8 respostas
  • Marko Smith

    Quão grande deve ser o mysql innodb_buffer_pool_size?

    • 4 respostas
  • Marko Smith

    Listar todas as colunas de uma tabela especificada

    • 5 respostas
  • Marko Smith

    restaurar a tabela do arquivo .frm e .ibd?

    • 10 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

    Como selecionar a primeira linha de cada grupo?

    • 6 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
    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
    pedrosanta Listar os privilégios do banco de dados usando o psql 2011-08-04 11:01:21 +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
  • Martin Hope
    bernd_k Quando devo usar uma restrição exclusiva em vez de um índice exclusivo? 2011-01-05 02:32:27 +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