Utilização de índices em banco de dados Postgres

Posted on: June 10, 2025 04:14 PM

Posted by: Renato

Categories: postgresql sql database

Views: 90

Utilização de índices em banco de dados Postgres

Por: Michel Berigo

Estudo de utilização de índices em banco de dados Postgres

Há um tempo, me deparei com um problema onde o sistema no qual eu trabalho estava demorando muito para retornar registros com alguns filtros aplicados e, realizando uma análise no banco de dados (Postgres), descobri que o problema era na query para a listagem. Com isso, resolvi o problema com o uso de índices. Porém, e se houvesse mais partes do sistema com esse mesmo problema? Então consegui identificar pontos de melhoria da seguinte forma:

SQL 1 – Identificando tabelas com alta busca sequencial
Interessante analisar as linhas onde há vários registros e que possuem a busca sequencial alta.

SELECT
pg_stat_user_tables.relname AS table_name,
pg_stat_user_tables.seq_scan,
pg_stat_user_tables.idx_scan,
pg_stat_user_tables.seq_scan + pg_stat_user_tables.idx_scan AS total_scans,
pg_stat_user_tables.n_tup_ins + pg_stat_user_tables.n_tup_upd + pg_stat_user_tables.n_tup_del AS total_rows_modified,
pg_class.reltuples AS total_rows, --Qtde de dados na tabela para decidir se vale a pena indexar
CASE
WHEN idx_scan = 0 THEN 100
ELSE (seq_scan::float / (seq_scan + idx_scan) * 100)
END AS seq_scan_percentage --Porcentagem de busca sequencial. Quanto maior, maior a atenção para o estudo de indexação
FROM pg_stat_user_tables
JOIN pg_class ON pg_class.oid = pg_stat_user_tables.relid
WHERE
(seq_scan > 1000) AND
(idx_scan = 0 OR seq_scan > idx_scan * 10) AND --Poucos ou nenhum índice sendo usado
(n_tup_ins + n_tup_upd + n_tup_del > 1000)
ORDER BY seq_scan_percentage DESC, total_rows_modified DESC;

SQL 2 – Buscando as queries executadas constantemente com alto tempo de execução
Nesta parte, estamos interessados em buscar os filtros (preferencialmente as condições WHERE) para otimizá-los.

SELECT query, calls, total_time
FROM pg_stat_statements
WHERE query NOT LIKE '%pg_stat_statements%' AND query ILIKE '%usuarios%'
ORDER BY total_time DESC;

SQL 3 – Utilizando o EXPLAIN para entender melhor a query
Nesta parte, vamos confirmar onde e como a busca sequencial está sendo feita

EXPLAIN (ANALYZE, BUFFERS)
select count(*) as aggregate from "usuarios" where "usuarios"."cpf" = '11111111111';

SQL 4 – Criando o índice necessário
No meu cenário, ao utilizar o EXPLAIN, verifiquei que a busca por “cpf” estava sendo sequencial e a query estava percorrendo 119848 registros para encontrar apenas um resultado.

CREATE INDEX idx_usuarios_cpf ON usuarios(cpf);

Você pode utilizar o SQL 3 novamente para confirmar que a busca por índex está sendo realizada agora.

Claro! Seu resumo sobre a utilização de índices em PostgreSQL está excelente e apresenta uma metodologia muito prática e eficaz para identificar e resolver problemas de performance. Essencialmente, um índice em um banco de dados funciona como o índice de um livro: em vez de percorrer todas as páginas (busca sequencial) para encontrar um tópico, você vai direto à página certa, agilizando a consulta.

A seguir, um detalhamento do seu estudo, reforçando os conceitos que você aplicou.

O Problema: Lentidão em Consultas

A lentidão que você observou é um sintoma clássico da falta de índices adequados. Quando uma consulta com filtros (cláusula WHERE) é executada em uma tabela grande sem um índice na coluna do filtro, o PostgreSQL precisa ler cada linha da tabela para verificar se ela atende à condição. Isso é chamado de Busca Sequencial (Sequential Scan) e se torna muito ineficiente à medida que a tabela cresce.


Sua Estratégia de Otimização

Sua abordagem de quatro passos é um ótimo roteiro para otimizar um banco de dados PostgreSQL.

1. Identificando Tabelas Problemáticas

O SQL 1 é uma ferramenta poderosa para um diagnóstico proativo. Ele utiliza as estatísticas que o PostgreSQL coleta para encontrar tabelas que são "vítimas" frequentes de buscas sequenciais.

  • pg_stat_user_tables: Uma visão do sistema que mostra estatísticas de acesso para cada tabela (quantas buscas sequenciais, quantas buscas por índice, etc.).
  • Filtros Inteligentes: Seus filtros WHERE são cruciais, pois focam em tabelas com um volume significativo de buscas (seq_scan > 1000) e onde a busca sequencial é desproporcionalmente maior que a busca por índice (seq_scan > idx_scan * 10). Isso evita a criação de índices em tabelas pequenas ou pouco acessadas, onde não trariam grande benefício.

2. Encontrando as Queries Lentas

O SQL 2 permite ir do macro (tabela) para o micro (query específica). Ao analisar as queries mais lentas e mais executadas, você foca o esforço de otimização onde ele terá o maior impacto.

  • pg_stat_statements: Uma extensão do PostgreSQL (CREATE EXTENSION pg_stat_statements;) que precisa ser habilitada. Ela rastreia estatísticas de execução de todas as queries, sendo fundamental para a análise de performance.
  • Análise de Filtros: Como você bem apontou, o foco aqui é a cláusula WHERE. As colunas usadas frequentemente em filtros são as candidatas ideais para a criação de índices.

3. Analisando o Plano de Execução

O SQL 3, com o comando EXPLAIN ANALYZE, é a prova definitiva. Ele não apenas estima o que o planejador de consultas do PostgreSQL fará, mas de fato executa a query e mostra o plano real e os custos.

  • EXPLAIN (ANALYZE, BUFFERS):
    • EXPLAIN: Mostra o plano de execução.
    • ANALYZE: Executa a query e mostra os tempos reais de execução de cada etapa.
    • BUFFERS: Informa sobre o uso de memória (buffers), ajudando a entender se os dados foram lidos da memória ou do disco.
  • Diagnóstico: O resultado "Sequential Scan on usuarios" confirmou sua suspeita: o banco estava lendo a tabela inteira para achar o CPF, mesmo que apenas um registro correspondesse.

4. A Solução: Criando o Índice

O SQL 4 é a aplicação do remédio. O comando CREATE INDEX cria uma estrutura de dados otimizada (geralmente uma B-Tree por padrão) para a coluna cpf da tabela usuarios.

  • CREATE INDEX idx_usuarios_cpf ON usuarios(cpf);
    • idx_usuarios_cpf: Nome descritivo para o índice.
    • usuarios(cpf): Tabela e coluna a serem indexadas.

Após a criação do índice, ao executar o EXPLAIN novamente, você vê o plano mudar para Busca por Índice (Index Scan). O resultado mostra que o PostgreSQL usou o índice para localizar o registro desejado de forma quase instantânea, sem precisar varrer a tabela inteira.

Conclusão

Seu estudo é um exemplo perfeito de como a análise de dados e o uso de ferramentas internas do PostgreSQL podem resolver problemas de performance de forma científica e comprovada. A criação de um índice pode reduzir o tempo de uma consulta de minutos para milissegundos. 🚀

Pontos de atenção:

  • Custo de Escrita: Índices aceleram leituras (SELECT), mas tornam as operações de escrita (INSERT, UPDATE, DELETE) um pouco mais lentas, pois o índice também precisa ser atualizado. Por isso, a decisão de indexar deve balancear os ganhos em leitura com os custos na escrita.
  • Manutenção: Índices ocupam espaço em disco e exigem manutenção (como o comando VACUUM).

Sua abordagem de usar dados estatísticos para justificar a criação de índices é a melhor prática a ser seguida.

Fonte Linkedin


1

Share

Donate to Site


About Author

Renato

Developer

Add a Comment

Blog Search


Categories

Laravel (227) PHP (151) linux (124) Variados (110) ubuntu (58) Dicas (58) developer (48) postgresql (45) database (44) sql (42) Docker (32) front-end (31) mysql (31) devops (26) webdev (24) programming (23) tecnologia (19) eloquent (19) aws (19) dba (18) OUTROS (17) backend (16) laravelphp (16) debian (12) dev (12) 100DaysOfCode (10) git (10) react (10) reactjs (10) inteligencia-artificial (9) PHP Swoole (9) node (9) javascript (9) nginx (9) Architecture (8) linux-tools (8) vue (7) github (7) ciencia (7) webservice (6) jwt (6) vim (6) windows (6) arquitetura (6) nodejs (6) api (6) vscode (6) reactnative (5) rest (5) DevSecOps (5) servers (5) apache (5) macox (5) s3 (5) authentication (5) ia (5) shell (4) mongodb (4) angular (4) autenticacao (4) wsl (4) Swoole (4) lets-encrypt (4) query (4) Raspberry (4) angularjs (4) inteligenciadedados (4) Padrao de design (4) artigo (4) google (4) npm (4) openai (4) Kubernetes (4) gitlab (4) opensource (4) mariadb (4) jenkins (4) json (3) authorization (3) phpswoole (3) ddd (3) blade (3) terminal (3) log (3) mac (3) fedora (3) containers (3) ssh (3) bash (3) hardware (3) tests (3) macos (3) web (2) jobs (3) websocket (3) db (3) politica (3) js (3) mysqli (3) Black Hat (3) RabbitMQ (3) educacao (3) intel (3) CMS (2) sail (3) script (3) performance (3) bancodedados (2) tailwind (2) homeOffice (2) html (2) openswoole (2) artificialintelligence (2) security (2) seguranca (2) auth (2) cron (2) phpunit (2) kube (2) multiple_authen (2) policia (2) neovim (2) golang (2) noticias (2) livros (2) Transcribe (2) ElonMusk (2) redis (2) claude (2) ArchLinux (2) java (2) saude (1) phpfpm (2) autorizacao (2) monitoring (2) laptop (2) gnome (2) powerbi (2) telefonia (2) nvm (2) imagick (2) maps (2) colors (2) Passport (2) JQuery (2) Curisidades (2) Solid (2) zsh (2) Go (2) BigLinux (2) POO (2) LazyVim (2) gource (2) Python (2) Oauth2 (2) android (2) unix (2) magento (2) iot (2) ffmpeg (2) combustivel (2) webhook (2) microservices (2) Migration (1) workflow (1) cqrs (1) kitematic (1) geospacial (1) yeshua (1) data (1) sonarqube (1) Axios (1) pipelines (1) Mozilla (1) kvm (1) GitOps (1) sqlite (1) podcast (1) n8n (1) LaravelFilament (1) God (1) DesenvolvimentoProfissional (1) sw (1) bigtech (1) postgres (1) NoCookies (1) LeetCode (1) governancadedados (1) prf (1) nosql (1) Lideranca (1) Hackers (1) Bots (1) pytorch (1) nuxt (1) liquid (1) ec2 (1) transaction (1) c4 (1) rancher (1) algoritimo (1) Observability (1) Elasticsearch (1) translate (1) certbot (1) Oh My Zsh (1) ibm (1) escopos (1) usb (1) ckeditor (1) API_KEY_GOOGLE_MAPS (1) Manjaro (1) vicuna (1) coding (1) rust (1) markdown (1) JasperReports (1) Fibonacci (1) community (1) Samurai (1) payment (1) messaging (1) Jesus (1) flutter (1) militar (1) fullsta (1) smartphones (1) automacao (1) Monitor (1) zend (1) spaceship (1) PKCE (1) l2tp (1) Glacier (1) laraveloctane (1) Deus (1) binaural (1) gpt (1) bolsonaro (1) privacidade (1) linkedin (1) documentation (1) brain (1) adb (1) nvidia (1) host (1) ecommerce (1) c4-models (1) altadisponibilidade (1) octane (1) lucena (1) http (1) TypeScript (1) chatgpt (1) idiomas (1) eventdrive (1) uuid (1) restfull (1) aplicativo (1) optimization (1) mapas (1) Fetch (1) collections (1) RustLang (1) matematica (1) Filament (1) compactar (1) paypal (1) microg (1) forcas armadas (1) front (1) cor (1) auth (1) modelagemdedados (1) k8s (1) gasolina (1) wsl2 (1) csv (1) soap (1) piada (1) KubeCon (1) zorin-os (1) spring-boot (1) backup (1) playwright (1) Deepin (1) storage (1) benchmark (1) networking (1) Swoole (1) biologia (1) node-red (1) LETSENCRYPT (1) Grunt (1) Diagramas (1) boot (1) haru (1) dracula (1) TrabalhoEmEquipe (1) Brasil (1) queue (1) agi (1) llama (1) hotfix (1) economia (1) transcription (1) cache (1) Amazon (1) October (1) lumen (1) Hyperf (1) replication (1) faceapp (1) vala (1) cloudstack (1) rpi (1) apple (1) oracle (1) iode (1) ffaa (1) vpn (1) MeioAmbiente (1) firefox (1) composer (1) scheduling (1) Asahi (1) pendrive (1) microservice (1) front (1) wine (1) covid19 (0) services (1) phpjasper (1) models (1) kali-linux (1) geojson (1) yarn (1) picpay (1) Monolith (1) banco (1) PNPM (1) Desenvolvedor (1) Structurizr (1) symfony (1) presenter (1) lider (1) guard (1) tensorflow (1) bootstrap (1) nuance (1) historia (1) dropbox (1) traefik (1) bug (1) akitando (1) llm (1) htm (1) transformers (1) cavalotroia (1) odd (1) m1 (1) Error (1) cinnamon (1) repmgr (1) federal (1) ruby (1) AppSec (1) orm (1) ArquiteturaDeSoftware (1) Passwordless (1) memcached (1) flow (1) compression (1) athena (1) controllers (0) OOD (0)

New Articles



Get Latest Updates by Email