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 / 25513
Accepted
davetapley
davetapley
Asked: 2012-10-06 10:29:23 +0800 CST2012-10-06 10:29:23 +0800 CST 2012-10-06 10:29:23 +0800 CST

Cache de índice do PostgreSQL

  • 772

Estou tendo dificuldade em encontrar explicações 'lay' de como os índices são armazenados em cache no PostgreSQL, então gostaria de uma verificação da realidade em qualquer uma ou todas essas suposições:

  1. Índices PostgreSQL, como linhas, vivem no disco, mas podem ser armazenados em cache.
  2. Um índice pode estar inteiramente no cache ou não estar.
  3. Se é armazenado em cache ou não, depende da frequência com que é usado (conforme definido pelo planejador de consulta).
  4. Por esta razão, a maioria dos índices 'sensatos' estarão no cache o tempo todo.
  5. Os índices residem no mesmo cache (o buffer cache?) que as linhas e, portanto, o espaço de cache usado por um índice não está disponível para as linhas.


Minha motivação para entender isso decorre de outra pergunta que fiz , onde foi sugerido que índices parciais podem ser usados ​​em tabelas onde a maioria dos dados nunca será acessada.

Antes de fazer isso, gostaria de deixar claro que empregar um índice parcial traz duas vantagens:

  1. Reduzimos o tamanho do índice no cache, liberando mais espaço para as próprias linhas no cache.
  2. Reduzimos o tamanho do B-Tree, resultando em uma resposta de consulta mais rápida.
postgresql performance
  • 2 2 respostas
  • 11658 Views

2 respostas

  • Voted
  1. Best Answer
    dezso
    2012-10-06T14:15:19+08:002012-10-06T14:15:19+08:00

    Brincando um pouco com pg_buffercache , pude obter respostas para algumas de suas perguntas.

    1. Isso é bastante óbvio, mas os resultados para (5) também mostram que a resposta é SIM
    2. Ainda estou para definir um bom exemplo para isso, por enquanto é mais sim do que não :) (Veja minha edição abaixo, a resposta é NÃO .)
    3. Como o planejador é quem decide se usa um índice ou não, podemos dizer SIM , ele decide o cache (mas isso é mais complicado)
    4. Os detalhes exatos do cache podem ser derivados do código-fonte, não consegui encontrar muito sobre esse tópico, exceto este (consulte a resposta do autor também). No entanto, tenho certeza de que isso é muito mais complicado do que um simples sim ou não. (Novamente, da minha edição, você pode ter uma ideia - como o tamanho do cache é limitado, esses índices 'sensatos' competem pelo espaço disponível. Se forem muitos, eles chutarão uns aos outros do cache - então a resposta é NÃO . )
    5. Como mostra uma consulta simples pg_buffercache, a resposta é um SIM definitivo . Vale a pena observar que os dados da tabela temporária não são armazenados em cache aqui.

    EDITAR

    Encontrei o excelente artigo de Jeremiah Peschka sobre armazenamento de tabelas e índices. Com informações de lá, eu poderia responder (2) também. Eu configurei um pequeno teste, para que você mesmo possa verificar.

    -- we will need two extensions
    CREATE EXTENSION pg_buffercache;
    CREATE EXTENSION pageinspect;
    
    
    -- a very simple test table
    CREATE TABLE index_cache_test (
          id serial
        , blah text
    );
    
    
    -- I am a bit megalomaniac here, but I will use this for other purposes as well
    INSERT INTO index_cache_test
    SELECT i, i::text || 'a'
    FROM generate_series(1, 1000000) a(i);
    
    
    -- let's create the index to be cached
    CREATE INDEX idx_cache_test ON index_cache_test (id);
    
    
    -- now we can have a look at what is cached
    SELECT c.relname,count(*) AS buffers
    FROM 
        pg_class c 
        INNER JOIN pg_buffercache b ON b.relfilenode = c.relfilenode 
        INNER JOIN pg_database d ON (b.reldatabase = d.oid AND d.datname = current_database())
    GROUP BY c.relname
    ORDER BY 2 DESC LIMIT 10;
    
                 relname              | buffers
    ----------------------------------+---------
     index_cache_test                 |    2747
     pg_statistic_relid_att_inh_index |       4
     pg_operator_oprname_l_r_n_index  |       4
    ... (others are all pg_something, which are not interesting now)
    
    -- this shows that the whole table is cached and our index is not in use yet
    
    -- now we can check which row is where in our index
    -- in the ctid column, the first number shows the page, so 
    -- all rows starting with the same number are stored in the same page
    SELECT * FROM bt_page_items('idx_cache_test', 1);
    
     itemoffset |  ctid   | itemlen | nulls | vars |          data
    ------------+---------+---------+-------+------+-------------------------
              1 | (1,164) |      16 | f     | f    | 6f 01 00 00 00 00 00 00
              2 | (0,1)   |      16 | f     | f    | 01 00 00 00 00 00 00 00
              3 | (0,2)   |      16 | f     | f    | 02 00 00 00 00 00 00 00
              4 | (0,3)   |      16 | f     | f    | 03 00 00 00 00 00 00 00
              5 | (0,4)   |      16 | f     | f    | 04 00 00 00 00 00 00 00
              6 | (0,5)   |      16 | f     | f    | 05 00 00 00 00 00 00 00
    ...
             64 | (0,63)  |      16 | f     | f    | 3f 00 00 00 00 00 00 00
             65 | (0,64)  |      16 | f     | f    | 40 00 00 00 00 00 00 00
    
    -- with the information obtained, we can write a query which is supposed to
    -- touch only a single page of the index
    EXPLAIN (ANALYZE, BUFFERS) 
        SELECT id 
        FROM index_cache_test 
        WHERE id BETWEEN 10 AND 20 ORDER BY id
    ;
    
     Index Scan using idx_test_cache on index_cache_test  (cost=0.00..8.54 rows=9 width=4) (actual time=0.031..0.042 rows=11 loops=1)
       Index Cond: ((id >= 10) AND (id <= 20))
       Buffers: shared hit=4
     Total runtime: 0.094 ms
    (4 rows)
    
    -- let's have a look at the cache again (the query remains the same as above)
                 relname              | buffers
    ----------------------------------+---------
     index_cache_test                 |    2747
     idx_test_cache                   |       4
    ...
    
    -- and compare it to a bigger index scan:
    EXPLAIN (ANALYZE, BUFFERS) 
    SELECT id 
        FROM index_cache_test 
        WHERE id <= 20000 ORDER BY id
    ;
    
    
     Index Scan using idx_test_cache on index_cache_test  (cost=0.00..666.43 rows=19490 width=4) (actual time=0.072..19.921 rows=20000 loops=1)
       Index Cond: (id <= 20000)
       Buffers: shared hit=4 read=162
     Total runtime: 24.967 ms
    (4 rows)
    
    -- this already shows that something was in the cache and further pages were read from disk
    -- but to be sure, a final glance at cache contents:
    
                 relname              | buffers
    ----------------------------------+---------
     index_cache_test                 |    2691
     idx_test_cache                   |      58
    
    -- note that some of the table pages are disappeared
    -- but, more importantly, a bigger part of our index is now cached
    

    Em suma, isso mostra que índices e tabelas podem ser armazenados em cache página por página, portanto, a resposta para (2) é NÃO .

    E uma última para ilustrar tabelas temporárias não armazenadas em cache aqui:

    CREATE TEMPORARY TABLE tmp_cache_test AS 
    SELECT * FROM index_cache_test ORDER BY id FETCH FIRST 20000 ROWS ONLY;
    
    EXPLAIN (ANALYZE, BUFFERS) SELECT id FROM tmp_cache_test ORDER BY id;
    
    -- checking the buffer cache now shows no sign of the temp table
    
    • 20
  2. Greg Smith
    2012-10-17T18:20:20+08:002012-10-17T18:20:20+08:00

    As páginas de índice são buscadas quando uma consulta decide que serão úteis para reduzir a quantidade de dados da tabela necessários para responder a uma consulta. Somente os blocos do índice navegados para realizar isso são lidos. Sim, eles vão para o mesmo pool shared_buffers onde os dados da tabela são armazenados. Ambos também são apoiados pelo cache do sistema operacional como uma segunda camada de cache.

    Você pode facilmente ter 0,1% de um índice na memória ou 100% dele. A ideia de que a maioria dos "índices 'sensatos' estarão no cache o tempo todo" cai por terra quando você tem consultas que tocam apenas um subconjunto de uma tabela. Um exemplo comum é se você tiver dados orientados ao tempo. Freqüentemente, eles geralmente navegam no final recente da mesa, raramente visitando a história antiga. Lá você pode encontrar todos os blocos de índice necessários para navegar para e ao redor do final recente na memória, enquanto muito poucos necessários para navegar nos registros anteriores estão lá.

    As partes complicadas da implementação não são como os blocos entram no cache do buffer. São as regras sobre quando eles saem. Minha conversa sobre o cache de buffer do PostgreSQL e as consultas de exemplo incluídas podem ajudá-lo a entender o que está acontecendo lá e ver o que realmente está se acumulando em um servidor de produção. Pode ser surpreendente. Há muito mais sobre todos esses tópicos em meu livro PostgreSQL 9.0 High Performance também.

    Os índices parciais podem ser úteis porque reduzem o tamanho do índice e, portanto, são mais rápidos de navegar e deixam mais RAM para armazenar em cache outras coisas. Se a sua navegação no índice é tal que as partes que você toca estão sempre na RAM, de qualquer maneira, isso pode não comprar uma melhoria real.

    • 10

relate perguntas

  • Sequências Biológicas do UniProt no PostgreSQL

  • Como determinar se um Índice é necessário ou necessário

  • Onde posso encontrar o log lento do mysql?

  • Como posso otimizar um mysqldump de um banco de dados grande?

  • 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