Eu tenho uma accounts
tabela com aproximadamente 200k linhas e um índice para essas colunas:
account_type_id BIGINT
, member_id BIGINT
, external_id VARCHAR(64)
CREATE INDEX account_full_qualifiers_idx
ON normal_object.account (account_type_id, member_id, external_id) TABLESPACE index_tbsp;
E tenho uma função que está realizando algum trabalho de ETL com a seguinte consulta:
EXECUTE '
SELECT * FROM normal_object.account
WHERE account_type_id = $1
AND member_id = $2
AND external_id = $3'
INTO e_row
USING r_row.account_type_id, r_row.member_id, r_row.external_id;
No entanto, o EXECUTE
comando está NOT
usando o índice e não sei por quê. Meu único palpite é que os tipos de dados não estão alinhados. No entanto , r_row.account_type_id
é um BIGINT
, r_row.member_id
é um BIGINT
e r_row.external_id
é um VARCHAR(64)
.
Alguma sugestão de por que não está usando o índice?
Como posso obtê-lo para usar o índice? (Já tentei enable_seqscan
partir.)
As consultas executadas com
EXECUTE
são replanejadas com os valores de parâmetro reais passados para ela todas as vezes. Como você está usando o Postgres 9.2, talvez nem preciseEXECUTE
:De qualquer forma, atualizar para o Postgres 9.3 (ou o próximo 9.4) pode ajudar um pouco mais.
Portanto, a menos que tenhamos uma incompatibilidade de tipo (como você já suspeitava) ou uma incompatibilidade de agrupamento , seu índice deve ser usado, se os valores dos parâmetros forem seletivos o suficiente (recuperando menos de ~ 5% da tabela), o que provavelmente é o caso .
Você escreve:
Mas como você sabe disso? Se
r_row
for declarado comorecord
, os tipos de dados das colunas são definidos na atribuição de uma linha real ...Precisamos ver a função plpgsql completa com cabeçalho e rodapé. E a definição exata da tabela.
COLLATE "C"
para o seu índice de tipo de charUm índice em uma
integer
coluna de tipo é muito mais eficiente do que umvarchar(64)
em qualquer caso. Se você precisar usar o tipo de caractere, mas não precisar classificar a coluna de acordo com sua configuração de agrupamento (como presumo), seria mais eficiente usar COLLATE "C" para índice e consulta.Sua consulta seria então:
LIMIT 1
pode ou não ser necessário. Seu índice não éUNIQUE
, embora...Ou você define a coluna da tabela com
COLLATE "C"
para começar. O índice e a consulta serão padronizados para o agrupamento da coluna.Isso pode ou não resolver a questão em questão - é uma boa ideia para a sua situação em qualquer caso .
Detalhes nesta resposta relacionada (capítulos "Strings and collation" e "Index":
Como obtenho com eficiência "a linha correspondente mais recente"?
O manual sobre "Suporte de agrupamento".