CONSEGUI!! caramba, passei o dia todo nisso, mas finalmente consegui uma
alternativa viável (14s pra cruzar 200.000 x 400)
Agradeço a quem tentou ajudar! E aproveitando para responder:
EXISTS tinha um tempo de execução semelhante, e IN não era possível, pois
eu precisava buscar pela palavra inteira em qualquer lugar da string do
nome do produto.
Segue minha solução:
utilizei query de Full Text Search (@@) aliado a um dicionário 'dummy'.
ALTER TEXT SEARCH DICTIONARY simple(dummy);
ALTER TEXT SEARCH CONFIGURATION portuguese ALTER MAPPING FOR asciiword
WITH simple;
com isso, a normalização do to_tsvector() e plainto_tsquery() ficam
'literais'.
na tabela products, criei uma coluna com indice 'tsvector_name' (tsvector),
rodando após a seguinte query:
UPDATE
products
SET
tsvector_name = to_tsvector(NAME)
e na tabela bad_words, fiz o mesmo, criando a coluna com indice
'tsquery_word' (tsquery) e rodando:
UPDATE
bad_words
SET
tsquery_word = plainto_tsquery('simple', word);
no final das contas, a query de busca final ficou:
SELECT
p.id,
p.name,
bw.*
FROM
products p
LEFT JOIN bad_words bw ON *p.tsvector_name @@ bw.tsquery_word*
WHERE
bw.id IS NULL
e tá resolvido! =)
Em 28 de novembro de 2013 15:52, Douglas Fabiano Specht <
[email protected]> escreveu:
>
>
>
> Em 28 de novembro de 2013 15:24, Douglas Fabiano Specht <
> [email protected]> escreveu:
>
>
>>
>>
>> Em 28 de novembro de 2013 14:00, Pedro Cavalheiro
>> <[email protected]>escreveu:
>>
>>> Boa tarde!
>>>
>>> Estou com um problema de performance em uma query, talvez alguém possa
>>> me ajudar!
>>>
>>> Situação:
>>>
>>> Postgres 9.1
>>> Tabela produtos (id, nome)
>>> Tabela bad_words (id, word)
>>>
>>> Preciso basicamente selecionar todos os registros de products, removendo
>>> os produtos cujo nome possui alguma palavra listada na tabela bad_words.
>>>
>>> Uma query para realizar isso, não é complexa... Daria pra fazer assim:
>>>
>>> SELECT
>>> p.id,
>>> p.name
>>> FROM
>>> products p
>>> LEFT JOIN bad_words bw ON p.name ~* bw.word
>>> WHERE
>>> bw.id IS NULL
>>>
>>> Acredito que meu problema seja no número de cruzamentos realizados.
>>> Minha tabela de produtos, atualmente está com 200.000 registros, e a
>>> previsão é aumentar até 7.000.000 nos próximos meses. A tabela bad_words
>>> atualmente possui em torno de 400 registros.
>>>
>>> Rodando a consulta acima, o processamento leva em torno de 20 minutos
>>> (Intel i5 2.9ghz, 8gb ram, hd 7200rpm), inviável para a aplicação...
>>>
>>> Sei que milagres não existem, mas acredito que haja algum modo de
>>> indexar os valores envolvidos nesta consulta, ou melhorar a query, com a
>>> finalidade de diminuir o tempo total. Alguém tem alguma ideia?
>>>
>>> Agradeço pela ajuda!
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>> _______________________________________________
>>> pgbr-geral mailing list
>>> [email protected]
>>> https://listas.postgresql.org.br/cgi-bin/mailman/listinfo/pgbr-geral
>>>
>>>
>> ola..
>> amigo, poderia postar um explain e a ddl das tabelas?
>> tentou utilizar um in ou exists?
>>
>>
>> --
>>
>> Douglas Fabiano Specht
>>
>
> Pedro
> criei as duas tabelas aqui e veja a diferença no explain
>
> SELECT
> p.id,
> p.name
> FROM
> products p
> LEFT JOIN bad_words bw ON p.name ~*bw.word
> WHERE
> bw.id IS NULL
>
> explain:
> "Nested Loop Left Join (cost=0.00..72167266.22 rows=1 width=37)"
> " Join Filter: ((p.name)::text ~* (bw.word)::text)"
> " Filter: (bw.id IS NULL)"
> " -> Seq Scan on products p (cost=0.00..4496.25 rows=245225 width=37)"
> " -> Materialize (cost=0.00..458.27 rows=19618 width=37)"
> " -> Seq Scan on bad_words bw (cost=0.00..360.18 rows=19618
> width=37)"
>
>
> mudei o select para um in(nao sei se essa a sua ideia)
>
> SELECT
> p.id,
> p.name
> FROM
> products p
> WHERE
> p.name in(select word from bad_words where id IS NUL)
>
> explain:
> "Hash Semi Join (cost=605.40..10006.16 rows=245225 width=37)"
> " Hash Cond: ((p.name)::text = (bad_words.word)::text)"
> " -> Seq Scan on products p (cost=0.00..4496.25 rows=245225 width=37)"
> " -> Hash (cost=360.18..360.18 rows=19618 width=33)"
> " -> Seq Scan on bad_words (cost=0.00..360.18 rows=19618
> width=33)"
>
>
>
>
> Veja que a opção 2 o custo é bem menor, veja se nao pode utilizar ela..
>
> --
>
> Douglas Fabiano Specht
>
> _______________________________________________
> pgbr-geral mailing list
> [email protected]
> https://listas.postgresql.org.br/cgi-bin/mailman/listinfo/pgbr-geral
>
>
_______________________________________________
pgbr-geral mailing list
[email protected]
https://listas.postgresql.org.br/cgi-bin/mailman/listinfo/pgbr-geral