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 / user-213834

zabop's questions

Martin Hope
zabop
Asked: 2024-10-15 23:01:34 +0800 CST

Como prever se um plano de consulta envolverá o uso de um índice?

  • 7

Estou usando a imagem docker mais recente do PostgreSQL para criar um BD local (em uma máquina Apple M1 Pro - MacOS Sonoma 14.5). Crio uma tabela table0com uma única coluna col0dentro dela e a preencho com strings aleatórias de 2 a 16 caracteres. Crio um trigram-index em col0e vacuum (analyze). Passos exatos:

create table public.table0 (
    col0 varchar(25)
);

select setseed(0.12343);

insert into table0 (col0)
select substring(md5(random()::text), 1, (2 + (random() * 14))::int)
from generate_series(1, 12345678);

create extension pg_trgm;
create index col0_gin_trgm_idx on table0 using gin (col0 gin_trgm_ops);

vacuum (analyze) table0;

Examino o plano de consulta para selecionar 200 linhas contendo a string abc:

explain analyze
select * from table0 where col0 like '%abc%' limit 200;

Saída, confirmando que o índice do trigrama não é, mas uma varredura sequencial é usada:

                                                     QUERY PLAN                                                     
--------------------------------------------------------------------------------------------------------------------
 Limit  (cost=0.00..351.78 rows=200 width=10) (actual time=0.313..15.640 rows=200 loops=1)
   ->  Seq Scan on table0  (cost=0.00..216614.79 rows=123154 width=10) (actual time=0.312..15.620 rows=200 loops=1)
         Filter: ((col0)::text ~~ '%abc%'::text)
         Rows Removed by Filter: 115643
 Planning Time: 4.401 ms
 Execution Time: 15.841 ms
(6 rows)

Entretanto, se em vez de procurar por linhas contendo abceu procurar por linhas contendo bcd:

explain analyze
select * from table0 where col0 like '%bcd%' limit 200;

Então obtenho um plano de consulta diferente, que agora inclui uma varredura de índice:

                                                               QUERY PLAN                                                               
----------------------------------------------------------------------------------------------------------------------------------------
 Limit  (cost=52.34..764.83 rows=200 width=10) (actual time=7.032..7.230 rows=200 loops=1)
   ->  Bitmap Heap Scan on table0  (cost=52.34..4394.94 rows=1219 width=10) (actual time=7.031..7.220 rows=200 loops=1)
         Recheck Cond: ((col0)::text ~~ '%bcd%'::text)
         Heap Blocks: exact=169
         ->  Bitmap Index Scan on col0_gin_trgm_idx  (cost=0.00..52.04 rows=1219 width=0) (actual time=5.100..5.100 rows=21264 loops=1)
               Index Cond: ((col0)::text ~~ '%bcd%'::text)
 Planning Time: 0.521 ms
 Execution Time: 7.366 ms
(8 rows)

Esta configuração pode não ser totalmente reproduzível na primeira tentativa, mesmo que setseed(0.12343);seja usada, já que analyze"coleta estatísticas com base em sua própria seleção aleatória de linhas" (veja o segundo parágrafo aqui ). Recriei a situação acima várias vezes e nunca precisei tentar as etapas de configuração mais de 4 vezes, então espero que seja facilmente reproduzível, mesmo que o código que forneço não seja totalmente determinístico. (Removi e reiniciei o contêiner docker entre as tentativas.)

Esta resposta dá uma explicação básica do porquê uma vez o scan sequencial e por que às vezes o scan de índice é usado. Ela também tem 2 sugestões sobre como desencorajar scans sequenciais: modificando random_page_coste STATISTICSvalores.

Eu defino random_page_costpara 1.1 (via ALTER DATABASE postgres SET random_page_cost = 1.1;). Eu também "aumento a quantidade de estatísticas coletadas" por analyze(via ALTER TABLE table0 ALTER COLUMN col0 SET STATISTICS 1000;). Depois de outro vacuum (analyze) table0;eu reexecuto:

explain analyze
select * from table0 where col0 like '%abc%' limit 200;

e dessa vez o col0_gin_trgm_idxíndice trigrama é de fato usado. Depois disso, recriei o cenário acima, e sem modificar random_page_costou STATISTICSexecutar novamente vacuum (analyze) table0;- isso também modificou o comportamento e causou uma troca de varredura sequencial para varredura de índice. Acredito que isso se deva à natureza não determinística das estatísticas coletadas por analyze.

Desta vez, em vez de poder disparar o uso do índice (o que posso fazer agora, principalmente graças à resposta mencionada ), gostaria de entender os detalhes sobre como a decisão é tomada entre a varredura sequencial e a varredura de índice . Idealmente, gostaria de poder prever se a consulta:

explain analyze
select * from table0 where col0 like '%xyz%' limit 200;

irá disparar uma varredura de índice ou uma varredura sequencial, sabendo xyz, e qualquer coisa relacionada a estatísticas ou configurações do banco de dados. Anteriormente, no contexto de uma pergunta semelhante, fui aconselhado a verificar SELECT name, setting FROM pg_settings WHERE name = ANY ( '{shared_buffers, effective_cache_size, random_page_cost, effective_io_concurrency, work_mem}'::text[]);. Ele retorna (antes de modificar as configurações padrão):

           name           | setting 
--------------------------+---------
 effective_cache_size     | 524288
 effective_io_concurrency | 1
 random_page_cost         | 4
 shared_buffers           | 16384
 work_mem                 | 4096
(5 rows)

Acho que esses valores têm um efeito na decisão de varredura sequencial vs varredura de índice. Espero que exista uma função f com duas saídas possíveis: varredura sequencial ou varredura de índice . Imagino que f pegue xyz, random_page_cost, estatísticas coletadas por analyze, etc como entradas. Gostaria de entender a lista de entradas (ou seja, o que é etc?) e o que f faz com elas.

Como posso prever se um plano de consulta envolverá o uso de um índice?

postgresql
  • 2 respostas
  • 111 Views
Martin Hope
zabop
Asked: 2024-10-12 05:02:23 +0800 CST

O plano de consulta parece depender do intervalo de tempo entre a consulta e a configuração da tabela?

  • 7

Estou trabalhando com PostgreSQL 17. Como exemplo, tenho uma tabela table0com uma coluna col0, com strings geradas aleatoriamente como valores indexados por GIN . Eu uso o seguinte setup.sqlpara criar tal tabela:

create table public.table0 (
    col0 varchar(25)
);

select setseed(0.12345);

insert into table0 (col0)
select substring(md5(random()::text), 1, (2 + (random() * 14))::int)
from generate_series(1, 12345678);

create extension pg_trgm;
create index col0_gin_trgm_idx on table0 using gin (col0 gin_trgm_ops);

vacuum (full, analyze) table0;

Usar select setseed(0.12345);garante que a tabela criada seja a mesma em cada execução de setup.sql. Gostaria de observar o plano de execução para uma consulta de correspondência de string parcial simples. Para fazer isso, uso query.sql:

explain (analyze, buffers)
select * from table0 where col0 like '%abc%' limit 500;

Para minha surpresa, o plano de execução da consulta não é constante, e aparentemente depende do tempo entre a criação da tabela e a execução da consulta. Para demonstrar isso, eu crio o seguinte script bash:

#!/bin/bash

set -o errexit
set -o nounset
set -o pipefail

rm -f records.txt

for i in {1..9}; do

    docker run \
        --name postgres-db \
        --env POSTGRES_DB=postgres \
        --env POSTGRES_USER=postgres \
        --env POSTGRES_PASSWORD=mysecretpassword \
        --publish 5432:5432\
        --detach postgres

    sleep 2 # wait for docker container to start

    PGPASSWORD=mysecretpassword psql \
        --host=localhost \
        --port=5432 \
        --username=postgres \
        --dbname=postgres \
        --set=ON_ERROR_STOP=1 \
        --file=setup.sql

    sleep $((RANDOM % 10))

    PGPASSWORD=mysecretpassword psql \
        --host=localhost \
        --port=5432 \
        --username=postgres \
        --dbname=postgres \
        --set=ON_ERROR_STOP=1 \
        --file=query.sql >> records.txt

    docker rm --force postgres-db

done

Este script configura a tabela, espera uma quantidade aleatória de até 10 segundos e, em seguida, executa o acima query.sql. Ele faz isso várias vezes. Ele salva query.sqlas saídas em records.txt. Eu olhei records.txte descobri que às vezes a varredura sequencial, às vezes a varredura de índice é usada para executar a consulta . Uma cat records.txt | grep "\->"versão filtrada (via ) de records.txt:

   ->  Bitmap Heap Scan on table0  (cost=52.34..4394.93 rows=1219 width=10) (actual time=11.526..15.200 rows=500 loops=1)
         ->  Bitmap Index Scan on col0_gin_trgm_idx  (cost=0.00..52.04 rows=1219 width=0) (actual time=9.559..9.559 rows=20852 loops=1)
   ->  Seq Scan on table0  (cost=0.00..216612.01 rows=122742 width=9) (actual time=0.068..17.788 rows=500 loops=1)
   ->  Bitmap Heap Scan on table0  (cost=52.34..4394.93 rows=1219 width=9) (actual time=5.963..8.939 rows=500 loops=1)
         ->  Bitmap Index Scan on col0_gin_trgm_idx  (cost=0.00..52.04 rows=1219 width=0) (actual time=4.144..4.144 rows=20852 loops=1)
   ->  Bitmap Heap Scan on table0  (cost=52.32..4377.97 rows=1214 width=9) (actual time=7.447..11.406 rows=500 loops=1)
         ->  Bitmap Index Scan on col0_gin_trgm_idx  (cost=0.00..52.01 rows=1214 width=0) (actual time=5.594..5.594 rows=20852 loops=1)
   ->  Bitmap Heap Scan on table0  (cost=52.33..4384.75 rows=1216 width=9) (actual time=6.660..11.991 rows=500 loops=1)
         ->  Bitmap Index Scan on col0_gin_trgm_idx  (cost=0.00..52.02 rows=1216 width=0) (actual time=4.744..4.745 rows=20852 loops=1)
   ->  Bitmap Heap Scan on table0  (cost=52.34..4394.93 rows=1219 width=9) (actual time=9.153..13.563 rows=500 loops=1)
         ->  Bitmap Index Scan on col0_gin_trgm_idx  (cost=0.00..52.04 rows=1219 width=0) (actual time=7.141..7.141 rows=20852 loops=1)
   ->  Bitmap Heap Scan on table0  (cost=52.31..4374.58 rows=1213 width=10) (actual time=10.078..13.199 rows=500 loops=1)
         ->  Bitmap Index Scan on col0_gin_trgm_idx  (cost=0.00..52.01 rows=1213 width=0) (actual time=8.108..8.108 rows=20852 loops=1)
   ->  Bitmap Heap Scan on table0  (cost=52.33..4384.76 rows=1216 width=10) (actual time=7.322..12.073 rows=500 loops=1)
         ->  Bitmap Index Scan on col0_gin_trgm_idx  (cost=0.00..52.02 rows=1216 width=0) (actual time=5.526..5.527 rows=20852 loops=1)
   ->  Seq Scan on table0  (cost=0.00..216610.51 rows=245232 width=9) (actual time=0.073..23.047 rows=500 loops=1)

O completo records.txté:

                                                               QUERY PLAN                                                               
----------------------------------------------------------------------------------------------------------------------------------------
 Limit  (cost=52.34..1833.55 rows=500 width=10) (actual time=11.527..15.249 rows=500 loops=1)
   Buffers: shared hit=4 read=435
   ->  Bitmap Heap Scan on table0  (cost=52.34..4394.93 rows=1219 width=10) (actual time=11.526..15.200 rows=500 loops=1)
         Recheck Cond: ((col0)::text ~~ '%abc%'::text)
         Heap Blocks: exact=428
         Buffers: shared hit=4 read=435
         ->  Bitmap Index Scan on col0_gin_trgm_idx  (cost=0.00..52.04 rows=1219 width=0) (actual time=9.559..9.559 rows=20852 loops=1)
               Index Cond: ((col0)::text ~~ '%abc%'::text)
               Buffers: shared hit=4 read=7
 Planning:
   Buffers: shared hit=51 read=13 dirtied=1
 Planning Time: 4.666 ms
 Execution Time: 15.657 ms
(13 rows)

                                                    QUERY PLAN                                                     
-------------------------------------------------------------------------------------------------------------------
 Limit  (cost=0.00..882.39 rows=500 width=9) (actual time=0.068..17.831 rows=500 loops=1)
   Buffers: shared read=1439
   ->  Seq Scan on table0  (cost=0.00..216612.01 rows=122742 width=9) (actual time=0.068..17.788 rows=500 loops=1)
         Filter: ((col0)::text ~~ '%abc%'::text)
         Rows Removed by Filter: 282649
         Buffers: shared read=1439
 Planning:
   Buffers: shared hit=55 read=9 dirtied=1
 Planning Time: 2.427 ms
 Execution Time: 17.918 ms
(10 rows)

                                                               QUERY PLAN                                                               
----------------------------------------------------------------------------------------------------------------------------------------
 Limit  (cost=52.34..1833.55 rows=500 width=9) (actual time=5.965..8.988 rows=500 loops=1)
   Buffers: shared hit=4 read=435
   ->  Bitmap Heap Scan on table0  (cost=52.34..4394.93 rows=1219 width=9) (actual time=5.963..8.939 rows=500 loops=1)
         Recheck Cond: ((col0)::text ~~ '%abc%'::text)
         Heap Blocks: exact=428
         Buffers: shared hit=4 read=435
         ->  Bitmap Index Scan on col0_gin_trgm_idx  (cost=0.00..52.04 rows=1219 width=0) (actual time=4.144..4.144 rows=20852 loops=1)
               Index Cond: ((col0)::text ~~ '%abc%'::text)
               Buffers: shared hit=4 read=7
 Planning:
   Buffers: shared hit=51 read=13 dirtied=1
 Planning Time: 2.427 ms
 Execution Time: 9.234 ms
(13 rows)

                                                               QUERY PLAN                                                               
----------------------------------------------------------------------------------------------------------------------------------------
 Limit  (cost=52.32..1833.89 rows=500 width=9) (actual time=7.448..11.454 rows=500 loops=1)
   Buffers: shared hit=4 read=435
   ->  Bitmap Heap Scan on table0  (cost=52.32..4377.97 rows=1214 width=9) (actual time=7.447..11.406 rows=500 loops=1)
         Recheck Cond: ((col0)::text ~~ '%abc%'::text)
         Heap Blocks: exact=428
         Buffers: shared hit=4 read=435
         ->  Bitmap Index Scan on col0_gin_trgm_idx  (cost=0.00..52.01 rows=1214 width=0) (actual time=5.594..5.594 rows=20852 loops=1)
               Index Cond: ((col0)::text ~~ '%abc%'::text)
               Buffers: shared hit=4 read=7
 Planning:
   Buffers: shared hit=81 read=13 dirtied=1
 Planning Time: 2.835 ms
 Execution Time: 11.721 ms
(13 rows)

                                                               QUERY PLAN                                                               
----------------------------------------------------------------------------------------------------------------------------------------
 Limit  (cost=52.33..1833.75 rows=500 width=9) (actual time=6.662..12.059 rows=500 loops=1)
   Buffers: shared hit=4 read=435
   ->  Bitmap Heap Scan on table0  (cost=52.33..4384.75 rows=1216 width=9) (actual time=6.660..11.991 rows=500 loops=1)
         Recheck Cond: ((col0)::text ~~ '%abc%'::text)
         Heap Blocks: exact=428
         Buffers: shared hit=4 read=435
         ->  Bitmap Index Scan on col0_gin_trgm_idx  (cost=0.00..52.02 rows=1216 width=0) (actual time=4.744..4.745 rows=20852 loops=1)
               Index Cond: ((col0)::text ~~ '%abc%'::text)
               Buffers: shared hit=4 read=7
 Planning:
   Buffers: shared hit=51 read=13 dirtied=1
 Planning Time: 3.332 ms
 Execution Time: 12.511 ms
(13 rows)

                                                               QUERY PLAN                                                               
----------------------------------------------------------------------------------------------------------------------------------------
 Limit  (cost=52.34..1833.55 rows=500 width=9) (actual time=9.154..13.621 rows=500 loops=1)
   Buffers: shared hit=4 read=435
   ->  Bitmap Heap Scan on table0  (cost=52.34..4394.93 rows=1219 width=9) (actual time=9.153..13.563 rows=500 loops=1)
         Recheck Cond: ((col0)::text ~~ '%abc%'::text)
         Heap Blocks: exact=428
         Buffers: shared hit=4 read=435
         ->  Bitmap Index Scan on col0_gin_trgm_idx  (cost=0.00..52.04 rows=1219 width=0) (actual time=7.141..7.141 rows=20852 loops=1)
               Index Cond: ((col0)::text ~~ '%abc%'::text)
               Buffers: shared hit=4 read=7
 Planning:
   Buffers: shared hit=51 read=13 dirtied=1
 Planning Time: 4.113 ms
 Execution Time: 14.018 ms
(13 rows)

                                                               QUERY PLAN                                                               
----------------------------------------------------------------------------------------------------------------------------------------
 Limit  (cost=52.31..1833.95 rows=500 width=10) (actual time=10.079..13.249 rows=500 loops=1)
   Buffers: shared hit=4 read=435
   ->  Bitmap Heap Scan on table0  (cost=52.31..4374.58 rows=1213 width=10) (actual time=10.078..13.199 rows=500 loops=1)
         Recheck Cond: ((col0)::text ~~ '%abc%'::text)
         Heap Blocks: exact=428
         Buffers: shared hit=4 read=435
         ->  Bitmap Index Scan on col0_gin_trgm_idx  (cost=0.00..52.01 rows=1213 width=0) (actual time=8.108..8.108 rows=20852 loops=1)
               Index Cond: ((col0)::text ~~ '%abc%'::text)
               Buffers: shared hit=4 read=7
 Planning:
   Buffers: shared hit=51 read=13 dirtied=1
 Planning Time: 3.596 ms
 Execution Time: 13.682 ms
(13 rows)

                                                               QUERY PLAN                                                               
----------------------------------------------------------------------------------------------------------------------------------------
 Limit  (cost=52.33..1833.75 rows=500 width=10) (actual time=7.323..12.126 rows=500 loops=1)
   Buffers: shared hit=4 read=435
   ->  Bitmap Heap Scan on table0  (cost=52.33..4384.76 rows=1216 width=10) (actual time=7.322..12.073 rows=500 loops=1)
         Recheck Cond: ((col0)::text ~~ '%abc%'::text)
         Heap Blocks: exact=428
         Buffers: shared hit=4 read=435
         ->  Bitmap Index Scan on col0_gin_trgm_idx  (cost=0.00..52.02 rows=1216 width=0) (actual time=5.526..5.527 rows=20852 loops=1)
               Index Cond: ((col0)::text ~~ '%abc%'::text)
               Buffers: shared hit=4 read=7
 Planning:
   Buffers: shared hit=51 read=13 dirtied=1
 Planning Time: 5.907 ms
 Execution Time: 12.485 ms
(13 rows)

                                                    QUERY PLAN                                                     
-------------------------------------------------------------------------------------------------------------------
 Limit  (cost=0.00..441.64 rows=500 width=9) (actual time=0.074..23.096 rows=500 loops=1)
   Buffers: shared read=1439
   ->  Seq Scan on table0  (cost=0.00..216610.51 rows=245232 width=9) (actual time=0.073..23.047 rows=500 loops=1)
         Filter: ((col0)::text ~~ '%abc%'::text)
         Rows Removed by Filter: 282649
         Buffers: shared read=1439
 Planning:
   Buffers: shared hit=51 read=13 dirtied=1
 Planning Time: 2.087 ms
 Execution Time: 23.218 ms
(10 rows)

Usei o Postgres 17 dockerizado para facilitar a reprodutibilidade.

Reiniciando o contêiner docker, executando setup.sqle então:

explain (analyze, buffers, settings)
select * from table0 where col0 like '%abc%' limit 500;

retorna:

                                                               QUERY PLAN                                                               
----------------------------------------------------------------------------------------------------------------------------------------
 Limit  (cost=52.32..1833.89 rows=500 width=9) (actual time=9.476..17.923 rows=500 loops=1)
   Buffers: shared hit=4 read=435
   ->  Bitmap Heap Scan on table0  (cost=52.32..4377.97 rows=1214 width=9) (actual time=9.475..17.858 rows=500 loops=1)
         Recheck Cond: ((col0)::text ~~ '%abc%'::text)
         Heap Blocks: exact=428
         Buffers: shared hit=4 read=435
         ->  Bitmap Index Scan on col0_gin_trgm_idx  (cost=0.00..52.01 rows=1214 width=0) (actual time=7.662..7.662 rows=20852 loops=1)
               Index Cond: ((col0)::text ~~ '%abc%'::text)
               Buffers: shared hit=4 read=7
 Planning:
   Buffers: shared hit=55 read=9 dirtied=1
 Planning Time: 5.597 ms
 Execution Time: 18.334 ms
(13 rows)

No entanto, não consigo entender por que às vezes é usada uma varredura sequencial e às vezes uma varredura de índice.

Por que um plano de consulta aparentemente depende do intervalo de tempo entre a consulta e a configuração da tabela?


Abaixo abordo algumas questões que surgiram nos comentários.

Há alguma outra atividade de gravação no BD?
Eu não iniciei nenhuma, e como é apenas um contêiner que eu executo na minha máquina local, a menos que haja algum processo automatizado do qual eu não esteja ciente, não há nenhuma atividade de gravação.

O quão ocupado está seu servidor de outra forma?
Não notei nada que não esteja funcionando bem. É um Apple M1 Pro, executando MacOS Sonoma 14.5.

postgresql
  • 1 respostas
  • 45 Views
Martin Hope
zabop
Asked: 2024-10-11 17:17:17 +0800 CST

O que devo fazer para que retornar 200 linhas seja pelo menos tão rápido quanto retornar 1.000 linhas ao executar consultas de correspondência parcial em uma coluna indexada?

  • 7

Tenho uma tabela PostgreSQL 17 table0. Ela tem uma única coluna col0contendo strings aleatórias de 2 a 16 caracteres. Gostaria de executar consultas de correspondência parcial, portanto, criei um índice GIN comgin_trgm_ops . Para minha surpresa, descobri que posso selecionar até 1000 linhas contendo abcmuito mais rápido do que até 200 linhas contendo abc. Configuração reproduzível:

Inicie o DB usando o Docker :

docker run \
    --name postgres-db \
    -e POSTGRES_DB=postgres \
    -e POSTGRES_USER=postgres \
    -e POSTGRES_PASSWORD=mysecretpassword \
    -p 5432:5432\
    -d postgres

Eu executo consultas usando o DBeaver ou salvando-as em query.sqle então:

PGPASSWORD=mysecretpassword psql \
    -h localhost \
    -p 5432 \
    -U postgres \
    -d postgres \
    -v ON_ERROR_STOP=1 \
    -f query.sql

Montar a mesa:

create table public.table0 (
    col0 varchar(25)
);

select setseed(0.12343);

insert into table0 (col0)
select substring(md5(random()::text), 1, (2 + (random() * 14))::int)
from generate_series(1, 12345678);

create extension pg_trgm;
create index col0_gin_trgm_idx on table0 using gin (col0 gin_trgm_ops);

vacuum (full, analyze) table0;

Verifique o plano de execução e o tempo de execução da seleção de 200 linhas contendo abc:

explain analyze
select * from table0 where col0 like '%abc%' limit 200;

Saída:

                                                    QUERY PLAN                                                     
-------------------------------------------------------------------------------------------------------------------
 Limit  (cost=0.00..352.27 rows=200 width=9) (actual time=0.672..49.646 rows=200 loops=1)
   ->  Seq Scan on table0  (cost=0.00..216621.29 rows=122985 width=9) (actual time=0.671..49.599 rows=200 loops=1)
         Filter: ((col0)::text ~~ '%abc%'::text)
         Rows Removed by Filter: 114081
 Planning Time: 4.540 ms
 Execution Time: 50.960 ms
(6 rows)

Verifique o plano de execução e o tempo de execução da seleção de até 1000 linhas contendo abc:

explain analyze
select * from table0 where col0 like '%abc%' limit 1000;

Saída:

                                                                 QUERY PLAN                                                                  
---------------------------------------------------------------------------------------------------------------------------------------------
 Limit  (cost=848.36..1369.03 rows=1000 width=9) (actual time=17.373..26.987 rows=1000 loops=1)
   ->  Bitmap Heap Scan on table0  (cost=848.36..64883.21 rows=122985 width=9) (actual time=17.371..26.931 rows=1000 loops=1)
         Recheck Cond: ((col0)::text ~~ '%abc%'::text)
         Heap Blocks: exact=846
         ->  Bitmap Index Scan on col0_gin_trgm_idx  (cost=0.00..817.62 rows=122985 width=0) (actual time=14.689..14.690 rows=21318 loops=1)
               Index Cond: ((col0)::text ~~ '%abc%'::text)
 Planning Time: 2.165 ms
 Execution Time: 27.356 ms
(8 rows)
                                                            

Como é visível, quando eu uso LIMIT 200, o mecanismo está fazendo um Seq Scan on table0, mas quando eu tenho LIMIT 1000, Bitmap Index Scan on col0_gin_trgm_idxé usado. Isso explica superficialmente por que a consulta usando LIMIT 200levou 4.540+50.960= 55.5 milissegundos, enquanto a LIMIT 1000consulta levou menos, 2.165+27.356=29.521 milissegundos.

Eu li (veja isto ou isto ) que idealmente eu não deveria tentar forçar o uso de índices em um ambiente de produção. Ingenuamente, parece que usar o índice para pesquisar por 200 linhas contendo abcseria mais rápido do que a varredura sequencial usada atualmente, assim como usar o índice para pesquisar por 1000 linhas é mais rápido do que pesquisar por 200 linhas usando varredura sequencial.

No meu cenário do mundo real ( instância do Aurora PostgreSQL em execução no AWS RDS ), essa diferença é limitante: quando preciso selecionar 25 linhas da minha tabela, é muito mais rápido selecionar 100 delas e então filtrar essas 100 por outros meios postgresql(ou posso simplesmente modificar o aplicativo para que selecionar 100 linhas em vez de 25 também seja aceitável).

Gostaria de saber se estou fazendo algo abaixo do ideal com a indexação ou se estou esquecendo de algo.

O que devo fazer para que a consulta com LIMIT 200seja pelo menos tão rápida quanto a consulta com LIMIT 1000?

Estou interessado principalmente em métodos aconselháveis ​​para uso em um ambiente de produção. É seguro assumir que table0não precisará ser modificado para editar seu conteúdo, nunca.

postgresql
  • 1 respostas
  • 101 Views

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