As consultas de texto completo nesse banco de dados (armazenando tíquetes RT ( Request Tracker )) parecem levar muito tempo para serem executadas. A tabela de anexos (contendo os dados de texto completo) tem cerca de 15 GB.
O esquema do banco de dados é o seguinte, são cerca de 2 milhões de linhas:
rt4 = # \ d + anexos Tabela "public.attachments" Coluna | Tipo | Modificadores | Armazenamento | Descrição ----------------- + ----------------------------- + - -------------------------------------------------- ------ + ---------- + ------------- id | inteiro not null default nextval ('attachments_id_seq' :: regclass) | planície | transactionid | inteiro não nulo | planície | pai | inteiro não nulo padrão 0 | planície | messageid | caracteres que variam (160) | | estendido | assunto | caracteres que variam (255) | | estendido | filename | caracteres que variam (255) | | estendido | tipo de conteúdo | caracteres variados (80) | | estendido | codificação de conteúdo | caracteres variados (80) | | estendido | conteúdo | texto | estendido | cabeçalhos | texto | estendido | criador | inteiro não nulo padrão 0 | planície | criado | registro de data e hora sem fuso horário | | planície | índice de conteúdo | tsvector | | estendido | Índices: "attachments_pkey" CHAVE PRIMÁRIA, btree (id) btree "attachments1" (pai) "attachments2" btree (transactionid) btree "attachments3" (pai, ID da transação) gin "contentindex_idx" (contentindex) Possui OIDs: não
Posso consultar o banco de dados por conta própria muito rapidamente (<1s) com uma consulta como:
select objectid
from attachments
join transactions on attachments.transactionid = transactions.id
where contentindex @@ to_tsquery('frobnicate');
No entanto, quando o RT executa uma consulta que deveria executar uma pesquisa de índice de texto completo na mesma tabela, geralmente leva centenas de segundos para concluir. A saída de análise da consulta é a seguinte:
Inquerir
SELECT COUNT(DISTINCT main.id)
FROM Tickets main
JOIN Transactions Transactions_1 ON ( Transactions_1.ObjectType = 'RT::Ticket' )
AND ( Transactions_1.ObjectId = main.id )
JOIN Attachments Attachments_2 ON ( Attachments_2.TransactionId = Transactions_1.id )
WHERE (main.Status != 'deleted')
AND ( ( ( Attachments_2.ContentIndex @@ plainto_tsquery('frobnicate') ) ) )
AND (main.Type = 'ticket')
AND (main.EffectiveId = main.id);
EXPLAIN ANALYZE
resultado
PLANO DE CONSULTA -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------- Agregado (custo = 51210.60..51210.61 linhas = 1 largura = 4) (tempo real = 477778.806..477778.806 linhas = 1 loops = 1) -> Loop aninhado (custo = 0,00..51210,57 linhas = 15 largura = 4) (tempo real = 17943,986..477775.174 linhas = 4197 loops = 1) -> Loop aninhado (custo = 0,00..40643,08 linhas = 6507 largura = 8) (tempo real = 8,526..20610,380 linhas = 1714818 loops = 1) -> Varredura Seq nos tickets principais (custo = 0,00..9818,37 linhas = 598 largura = 8) (tempo real = 0,008..256,042 linhas = 96990 loops = 1) Filtro: (((status) :: texto 'excluído' :: texto) AND (id = eficazid) AND ((tipo) :: texto = 'ticket' :: texto)) -> Varredura de índice usando transações1 em transações transações_1 (custo = 0,00..51,36 linhas = 15 largura = 8) (tempo real = 0,102..0,202 linhas = 18 loops = 96990) Índice Cond: (((objecttype) :: text = 'RT :: Ticket' :: text) AND (objectid = main.id)) -> Varredura de índice usando anexos2 em anexos anexos_2 (custo = 0,00..1,61 linhas = 1 largura = 4) (tempo real = 0,266..0,266 linhas = 0 loops = 1714818) Cond do índice: (transactionid = transaction_1.id) Filtro: (contentindex @@ plainto_tsquery ('frobnicate' :: texto)) Tempo de execução total: 477778.883 ms
Pelo que sei, o problema parece ser que ele não está usando o índice criado no contentindex
campo ( contentindex_idx
), mas está fazendo um filtro em um grande número de linhas correspondentes na tabela de anexos. As contagens de linhas na saída de explicação também parecem ser muito imprecisas, mesmo depois de uma recente ANALYZE
: linhas estimadas = 6507 linhas reais = 1714818.
Não tenho muita certeza de onde ir com isso.