Não, o PostgreSQL não aceita hints e nunca aceitará. É um erro achar
que hints são uma solução para esse tipo de problemas, normalmente
eles causam mais problemas do que resolvem. Nem sempre usar um
índice é o melhor caminho para uma consulta e isso varia com o
volume das tabelas envolvidas.
Flavio,
Discordo sobre Hints, pois imagine a situação abaixo:
//
torce_para count(*)
-------------- ----------
São Paulo 4.000.000
Corinthians 8.000.000
Palmeiras 6.000.000
Santos 2.000.000
VOCEM de Assis 8
Se existe um índice em torce_para e uma query pedir todos os torcedores
do VOCEM de Assis, é muito provável que o PostgreSQL fará "Sequencial
Scan" (full table scan - Oracle). É muito mais barato para o Otimizador
fazer um Sequencial Scan que um acesso a milhões de linhas do índice.
Ou o planejador do Oracle é uma bosta (e por isso precisa de hint mesmo
pra funcionar) ou você se enganou, colega. Eu espero que você tenha
realmente se enganado.
Veja meu exemplo, fiz agora aqui em cinco minutinhos e reproduzi seu
cenário:
psql (9.3.4)
Digite "help" para ajuda.
flavio=# create table torcedores (torce_para text);
CREATE TABLE
flavio=# insert into torcedores (torce_para) select 'São Paulo' from
(select generate_series (1, 4000000)) a;
INSERT 0 4000000
flavio=# insert into torcedores (torce_para) select 'Corinthians' from
(select generate_series (1, 8000000)) a;
INSERT 0 8000000
flavio=# insert into torcedores (torce_para) select 'Palmeiras' from
(select generate_series (1, 6000000)) a;
INSERT 0 6000000
flavio=# insert into torcedores (torce_para) select 'Santos' from
(select generate_series (1, 2000000)) a;
INSERT 0 2000000
flavio=# insert into torcedores (torce_para) select 'VOCEM de Assis'
from (select generate_series (1, 8)) a;
INSERT 0 8
flavio=# create index torce_para_idx on torcedores (torce_para);
CREATE INDEX
Agora o que interessa:
flavio=# SELECT torce_para, count(torce_para) FROM torcedores GROUP BY
torce_para;
torce_para | count
----------------+---------
Corinthians | 8000000
Palmeiras | 6000000
Santos | 2000000
São Paulo | 4000000
VOCEM de Assis | 8
(5 registros)
flavio=# EXPLAIN ANALYZE SELECT * FROM torcedores WHERE torce_para =
'VOCEM de Assis';
QUERY PLAN
---------------------------------------------------------------------------------------------------------------------------------
Index Only Scan using torce_para_idx on torcedores (cost=0.56..8.58
rows=1 width=10) (actual time=0.341..0.343 rows=8 loops=1)
Index Cond: (torce_para = 'VOCEM de Assis'::text)
Heap Fetches: 8
Total runtime: 0.361 ms
(4 registros)
Logo, sua afirmativa é *errada* e o planejador do PostgreSQL entendeu
direitinho que o índice é bastante útil ali. Vamos tentar para um dos
outros times:
flavio=# EXPLAIN ANALYZE SELECT * FROM torcedores WHERE torce_para =
'Corinthians';
QUERY PLAN
---------------------------------------------------------------------------------------------------------------------------
Seq Scan on torcedores (cost=0.00..356142.50 rows=8000522 width=10)
(actual time=336.863..2077.353 rows=8000000 loops=1)
Filter: (torce_para = 'Corinthians'::text)
Rows Removed by Filter: 12000008
Total runtime: 2356.269 ms
(4 registros)
Uhm... faz sentido, afinal, é uma fatia grande da tabela.
Agora vamos tentar imitar a ridícula funcionalidade "hint" do Oracle
usando algo mais moderno:
flavio=# set enable_seqscan = off;
SET
flavio=# EXPLAIN ANALYZE SELECT * FROM torcedores WHERE torce_para =
'Corinthians';
QUERY PLAN
--------------------------------------------------------------------------------------------------------------------------------------------
Bitmap Heap Scan on torcedores (cost=181688.61..387842.13
rows=8000522 width=10) (actual time=727.201..1726.837 rows=8000000
loops=1)
Recheck Cond: (torce_para = 'Corinthians'::text)
Rows Removed by Index Recheck: 115
-> Bitmap Index Scan on torce_para_idx (cost=0.00..179688.48
rows=8000522 width=0) (actual time=725.187..725.187 rows=8000000
loops=1)
Index Cond: (torce_para = 'Corinthians'::text)
Total runtime: 2003.549 ms
(6 registros)
Você vai me dizer que isso saiu mais rápido que a consulta anterior, mas
com custo mais alto, note. Saiu mais rápido por causa dos dados em cache
do exemplo anterior, infelizmente.
Vou reiniciar o PostgreSQL e a máquina pra limpar o cache e refazer:
flavio=# set enable_seqscan = off;
SET
flavio=# EXPLAIN ANALYZE SELECT * FROM torcedores WHERE torce_para =
'Corinthians';
QUERY
PLAN
--------------------------------------------------------------------------------------------------------------------------------------------
Bitmap Heap Scan on torcedores (cost=183446.83..391336.64
rows=8067905 width=10) (actual time=764.227..1757.159 rows=8000000 loops=1)
Recheck Cond: (torce_para = 'Corinthians'::text)
Rows Removed by Index Recheck: 115
-> Bitmap Index Scan on torce_para_idx (cost=0.00..181429.85
rows=8067905 width=0) (actual time=762.044..762.044 rows=8000000 loops=1)
Index Cond: (torce_para = 'Corinthians'::text)
Total runtime: 10036.530 ms
(6 registros)
Uhm... é, 10 segundos pra usar o índice, 2 segundos pro seqscan.
Ainda bem que não meti um *hint* ali né?
Se voce tiver a possibilidade de inserir um Hint poderia resolver a
query muito mais rápido, forçando o uso do indice, pois sao somente 8
registros. Outra opção seria criar um Histograma.
Como mostrei, o PostgreSQL executou a consulta exatamente sobre o índice.
Sobre histogramas, o sistema de estatísticas do PostgreSQL usa
exatamente esta técnica para determinar os custos.
Outro motivo que se utiliza Hint é para configurar grau de paralelismo
em queries, mas no PostgreSQL até a versão 8 eu sei que não tem isso
implementado. Alguém sabe se o PostgreSQL atual trabalha com paralelismo?
Do jeito que você está chamando de paralelismo, não, isso não existe
internamente ainda hoje no PostgreSQL, estudos sobre isso estão em
andamento.
mais restritivos através de alias de tabela +- como abaixo, assim na
hora da junção teria menos dados para fazer os Hash Join ou
Nested Loop:
SELECT *
FROM C1,
( SELECT * FROM C2 WHERE FILTRO = QUALQUER ) C2A
WHERE
....
Você olhou a consulta do colega antes de dizer isso?
Não, acabei nao observando o Link para a Query!
Sem ressentimentos, acontece.
Agradecemos por ter respondido corretamente, sem top post, desta vez.
Acho que não deixamos passar nada.
[]s
Flavio Gurgel
_______________________________________________
pgbr-geral mailing list
[email protected]
https://listas.postgresql.org.br/cgi-bin/mailman/listinfo/pgbr-geral