Criar backends de IA com o Banco de Dados do Azure para PostgreSQL
Projete uma base PostgreSQL gerenciada para memória persistente de agentes, proteja-a com Microsoft Entra ID e TLS, modele dados relacionais e JSONB, escreva SQL eficiente e integre aplicações Python com psycopg.
Tempo de estudo sugerido: 125 minutos • Nível intermediário • Reescrita autoral completa com versão resumida de cada tópico, avaliação comentada e laboratório guiado de memória de agente
Por João Ricardo Dutra••Conteúdo autoral completo
1. Partir do requisito de memória persistente
Imagine um agente de pesquisa que precisa retomar conversas, preservar tarefas de várias etapas e recuperar contexto para milhares de usuários simultâneos com latência inferior a um segundo. O banco deve garantir integridade relacional para usuários, sessões, mensagens e checkpoints, mas também acomodar variáveis de modelos e ferramentas. PostgreSQL reúne transações, SQL, JSONB, índices e extensões para atender aos dois lados.
Operar o mecanismo por conta própria também transfere à equipe servidores, correções, backups, , capacidade e segurança. O assume essas tarefas de plataforma sem romper a compatibilidade com o PostgreSQL da comunidade e suas ferramentas.
Explicar a arquitetura e as opções de computação.
Conectar com e .
Modelar tabelas, relações, restrições, JSONB e índices.
Usar recursos SQL específicos do PostgreSQL.
Integrar Python com psycopg e conexões reutilizáveis.
Resumo do tópico
O módulo transforma PostgreSQL em memória durável do agente enquanto o administra a plataforma de banco de dados.
2. Entender a arquitetura PostgreSQL gerenciada
O executa o mecanismo comunitário como serviço relacional totalmente gerenciado. Computação e armazenamento são componentes separados: o mecanismo usa computação baseada em Linux, enquanto os arquivos ficam no armazenamento gerenciado do com cópias localmente redundantes. Assim, capacidade de processamento e armazenamento podem evoluir de forma independente.
A equipe ainda controla parâmetros, janelas de manutenção, alta disponibilidade, extensões e dimensionamento. A Microsoft cuida do provisionamento físico, das correções da plataforma, da orquestração de backups e da infraestrutura gerenciada de disponibilidade.
O plano gerenciado remove trabalho de infraestrutura sem esconder os recursos de desenvolvimento e configuração do PostgreSQL.
Resumo do tópico
O serviço separa computação de armazenamento durável e delega as operações da plataforma à Microsoft.
3. Escolher computação, backup e recuperação
Camadas de computação por perfil de carga.
Camada
Melhor uso
Sinal de projeto
Expansível
Desenvolvimento, prova de conceito e cargas pequenas ou intermitentes.
Economia é mais importante que CPU sustentada.
Uso Geral
, e aplicações de produção típicas.
É necessário equilíbrio de memória e desempenho previsível.
Otimizado para Memória
grandes, SQL analítico e conjuntos ativos em memória.
Memória por vCPU é o recurso limitante.
É possível mudar de camada depois da implantação, normalmente com uma breve reinicialização. A escolha deve nascer das métricas de CPU, memória, conexões e latência, não da ideia de que a maior camada é sempre a mais segura.
Os backups automáticos combinam instantâneos e de transação. A retenção começa em sete dias e pode chegar a 35. O serviço utiliza armazenamento com redundância de zona onde disponível e redundância local nas demais regiões, criptografa com -256 e aceita chaves gerenciadas pela plataforma ou pelo cliente. A restauração pontual cria outro servidor no segundo escolhido dentro da retenção.
Resumo do tópico
Escolha a computação pelo comportamento real da carga e alinhe a retenção de sete a 35 dias ao objetivo de recuperação.
4. Planejar extensões e pool de conexões
Extensões acrescentam tipos, funções, operadores e métodos de índice sem alterar o núcleo. Soluções de IA podem avaliar pgvector para embeddings e vizinhos próximos, pg_trgm para semelhança textual e preenchimento automático, hstore para atributos chave-valor e PostGIS para geoespacial. Confirme a disponibilidade antes de depender da extensão e planeje suas atualizações.
O PgBouncer interno mantém conexões de servidor reutilizáveis e multiplexa clientes de curta duração. Ele ajuda quando cada inferência grava mensagens ou recupera contexto. O recurso integrado existe nas camadas Uso Geral e Otimizado para Memória, não na Expansível, e usa a porta 6432 em vez da porta PostgreSQL direta 5432.
az postgres flexible-server parameter set \
--resource-group rg-ai-agent \
--server-name pg-ai-agent \
--name pgbouncer.enabled \
--value true
# Direct PostgreSQL: 5432
# Built-in PgBouncer: 6432
Resumo do tópico
Valide extensões no projeto e use o PgBouncer interno em camadas compatíveis quando houver muita rotatividade de conexões.
5. Montar uma conexão PostgreSQL completa
O do servidor flexível segue <servidor>.postgres.database..com. Ele resolve para endereço público quando o acesso público está ativo ou privado com integração à . O cliente precisa de host, banco, usuário, credencial, porta e modo .
Parâmetros da conexão.
Parâmetro
Finalidade
Host
FQDN do servidor.
Porta
5432 para PostgreSQL direto ou 6432 para PgBouncer interno.
Banco
Banco de destino; a conexão não consulta diretamente outro banco.
Usuário e credencial
Senha PostgreSQL ou temporário do .
sslmode
Controla criptografia e validação de certificado.
Bibliotecas aceitam , pares de palavras-chave ou parâmetros separados. Mantenha a configuração fora do código-fonte e nunca registre segredos ou em .
Resumo do tópico
Uma conexão correta combina , porta, banco, identidade, credencial e política em uma configuração testável.
6. Preferir autenticação do
A autenticação do substitui senhas persistentes por . Ela centraliza governança, permite identidades gerenciadas em recursos do , gera rastros nos de entrada e reduz exposição porque o expira. Configure um administrador do Entra no servidor e solicite um para o recurso PostgreSQL.
from azure.identity import DefaultAzureCredential
credential = DefaultAzureCredential()
access_token = credential.get_token(
"https://ossrdbms-aad.database.windows.net/.default"
)
# Pass access_token.token as the PostgreSQL password.
DefaultAzureCredential pode usar no e credenciais da CLI do durante o desenvolvimento local; o é enviado como senha PostgreSQL. A autenticação nativa continua útil para legados, identidades externas ao locatário ou ambientes desconectados. Nesse caso, armazene senhas no , faça rotação, gere valores fortes e conceda privilégio mínimo.
Identidade, transporte criptografado, alcance de rede e pool são camadas diferentes da conexão segura.
Resumo do tópico
do e identidades gerenciadas removem senhas duradouras; credenciais nativas exigem gestão rigorosa de segredos.
7. Exigir e compreender o acesso de rede
O exige transporte criptografado e oferece 1.2 e 1.3. No cliente, disable é rejeitado; allow e prefer não validam o servidor; require força criptografia sem validar o certificado; verify- valida a cadeia; verify-full também confirma que o nome do certificado corresponde ao host.
Em produção, use verify-full e confie nas autoridades raiz DigiCert ou Microsoft apropriadas. Se a validação falhar, corrija o repositório de confiança em vez de reduzir a proteção.
No acesso público, regras de firewall limitam os IPs que chegam ao . No acesso privado, o servidor tem endereço na e o cliente deve estar na mesma rede, em uma rede emparelhada ou conectado por /ExpressRoute. Uma identidade válida não corrige uma rota bloqueada.
Resumo do tópico
Use verify-full e diagnostique identidade, ,, rota e firewall como camadas independentes.
8. Organizar servidores, bancos e esquemas
Um servidor hospeda vários bancos; cada conexão aponta para um deles e não realiza joins diretos entre bancos. Dentro do banco, esquemas são namespaces de tabelas, funções e outros objetos. public é o padrão quando o nome do esquema não é informado.
Use bancos separados para isolamento forte, restauração independente ou aplicações que não devem compartilhar dados. Use esquemas quando domínios relacionados ainda precisam de chaves estrangeiras e joins, para separar locatários logicamente ou simplificar permissões. Para muitas aplicações de IA, um banco com o esquema public basta.
Resumo do tópico
Bancos fornecem isolamento forte; esquemas organizam objetos relacionados sem impedir joins e relações.
9. Modelar memória do agente com tipos e restrições
CREATE TABLE agent_conversations (
id BIGSERIAL PRIMARY KEY,
session_id UUID NOT NULL UNIQUE,
user_id VARCHAR(255) NOT NULL,
started_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
ended_at TIMESTAMPTZ,
metadata JSONB NOT NULL DEFAULT '{}'::jsonb
);
CREATE TABLE agent_messages (
id BIGSERIAL PRIMARY KEY,
conversation_id BIGINT NOT NULL
REFERENCES agent_conversations(id) ON DELETE CASCADE,
role VARCHAR(20) NOT NULL
CHECK (role IN ('user', 'assistant', 'system')),
content TEXT NOT NULL,
created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP
);
CREATE INDEX ix_agent_messages_context
ON agent_messages(conversation_id, created_at, id);
Toda tabela precisa de chave primária estável. SERIAL e BIGSERIAL geram sequências de 32 e 64 bits; com gen_random_uuid() permite criar identificadores fora do banco ou combinar origens. BIGSERIAL é simples e eficiente para inserções centralizadas de grande volume.
Tipos úteis para de IA.
Tipo
Uso
JSONB
aninhados variáveis com armazenamento binário, operadores e índices.
TEXT / VARCHAR(n)
Texto sem limite ou comprimento máximo imposto pelo banco; VARCHAR sem limite e TEXT têm desempenho equivalente.
TIMESTAMPTZ
Datas com fuso, guardadas em UTC e exibidas conforme a sessão.
BYTEA
Pequenos binários ao lado dos dados; arquivos grandes ficam melhor no com uma referência.
BIGSERIAL /
Identidade sequencial do banco ou identidade global gerada pela aplicação.
NOT NULL bloqueia ausência, DEFAULT preenche valor omitido, CHECK limita domínios como status e UNIQUE evita duplicidade. As regras protegem os dados mesmo quando várias aplicações escrevem.
Resumo do tópico
Use colunas relacionais para fatos estáveis, JSONB para variabilidade controlada e restrições como última barreira de integridade.
10. Definir relações, índices e mudanças seguras
A chave estrangeira representa relações um-para-muitos, como conversa e mensagens. RESTRICT impede exclusão com dependentes; CASCADE propaga a exclusão; SET NULL e SET DEFAULT preservam o filho com referência alterada. Use cascata apenas quando remover o pai realmente deve remover todos os filhos. Relações muitos-para-muitos usam tabela de junção com chave primária composta.
O PostgreSQL indexa automaticamente chaves primárias e UNIQUE, mas não cria todo índice de consulta ou de chave estrangeira. B-tree atende igualdade, intervalos, joins e ordenação. A ordem de um índice composto importa: (conversation_id, created_at) atende o prefixo conversation_id, mas não uma filtragem apenas por created_at. Índices ocupam espaço e tornam gravações mais caras.
ALTER TABLE evolui a estrutura e DROP TABLE remove tabela e dados. A maioria do DDL é transacional: envolva mudanças relacionadas em BEGIN/COMMIT e faça diante de falha. Algumas operações adquirem bloqueios fortes; teste e agende. Tenha cuidado especial com DROP ... CASCADE.
Resumo do tópico
Relações impõem propriedade, índices seguem os acessos reais e DDL transacional reduz alterações parciais.
11. Respeitar a ordem SQL e os filtros do PostgreSQL
Ordem lógica do processamento SQL.
Ordem
Cláusula
Função
1
FROM
Monta as linhas de origem.
2
WHERE
Filtra linhas.
3
GROUP BY
Cria grupos.
4
HAVING
Filtra grupos.
5
SELECT
Projeta colunas e calcula aliases.
6
ORDER BY
Ordena o resultado.
7
LIMIT / OFFSET
Limita as linhas retornadas.
Um alias definido no SELECT ainda não existe em WHERE, GROUP BY ou HAVING. Repita a expressão ou mova-a para subconsulta/CTE; ORDER BY pode usar o alias porque ocorre depois. ILIKE faz correspondência sem diferenciar maiúsculas, NULLS FIRST/LAST controla nulos na ordenação e COALESCE devolve o primeiro valor não nulo.
Resumo do tópico
A ordem lógica explica o alcance de aliases; ILIKE, ordenação explícita de nulos e COALESCE simplificam consultas.
12. Consultar JSONB e evitar OFFSET profundo
-> retorna e ->> retorna texto; #> e #>> percorrem caminhos aninhados. ? verifica a existência de uma chave e @> testa contenção. Índices GIN podem acelerar esses filtros em coleções grandes. jsonb_array_elements_text expande arrays para filtragem e agregação.
OFFSET piora conforme a página avança, pois o mecanismo lê e descarta as linhas anteriores. A paginação por chave guarda os últimos valores ordenáveis e continua a partir deles. Acrescente um desempate exclusivo, como id junto ao timestamp, para não repetir ou perder linhas com a mesma data.
SELECT id, session_id, metadata->>'model' AS model, started_at
FROM agent_conversations
WHERE user_id = $1
AND metadata @> $2::jsonb
AND (started_at, id) < ($3, $4)
ORDER BY started_at DESC, id DESC
LIMIT 20;
Resumo do tópico
Use operadores JSONB para flexíveis e paginação por chave para desempenho estável em resultados extensos.
13. Compor consultas com CTEs e recursão
Uma Common Table Expression nomeia um resultado temporário válido somente na instrução. Ela divide uma consulta complexa em etapas legíveis, como sessões recentes seguidas por totais de mensagens.
WITH recent_sessions AS (
SELECT id, user_id, started_at
FROM agent_conversations
WHERE started_at >= CURRENT_DATE - INTERVAL '7 days'
), message_totals AS (
SELECT conversation_id, COUNT(*) AS message_count
FROM agent_messages
GROUP BY conversation_id
)
SELECT r.user_id, r.started_at,
COALESCE(m.message_count, 0) AS message_count
FROM recent_sessions r
LEFT JOIN message_totals m ON m.conversation_id = r.id;
WITH RECURSIVE percorre árvores de tarefas, estruturas organizacionais e threads ao combinar uma âncora com um ramo recursivo. Inclua condição de término ou limite de profundidade para que ciclos nos dados não executem indefinidamente.
Resumo do tópico
CTEs tornam SQL em etapas auditáveis; CTEs recursivas atravessam hierarquias com segurança quando possuem término.
14. Reduzir viagens com RETURNING e upserts
RETURNING recupera IDs, timestamps e valores modificados por INSERT, UPDATE ou sem outra consulta. É ideal quando o ID da conversa recém-criada será usado imediatamente nas mensagens.
INSERT ... ON CONFLICT reage a colisões de chave exclusiva. DO NOTHING ignora o duplicado; DO UPDATE usa a pseudotabela EXCLUDED para mesclar os valores propostos. Um WHERE condicional evita atualização inútil. O padrão atende checkpoints, preferências e operações idempotentes do agente.
INSERT INTO task_checkpoints (task_id, step_number, state)
VALUES ($1, $2, $3::jsonb)
ON CONFLICT (task_id, step_number)
DO UPDATE SET state = EXCLUDED.state,
updated_at = CURRENT_TIMESTAMP
RETURNING id, updated_at;
Resumo do tópico
RETURNING economiza uma ida ao banco e ON CONFLICT converte gravações repetíveis em operações idempotentes.
15. Integrar Python com segurança usando psycopg 3
psycopg 3 é o adaptador moderno de PostgreSQL para Python, com síncrona e assíncrona, recursos do mecanismo e pool opcional. O extra binary facilita desenvolvimento; builds de produção que exigem uma libpq específica podem compilar com seus cabeçalhos.
import psycopg
from psycopg_pool import ConnectionPool
pool = ConnectionPool(conninfo, min_size=1, max_size=10)
def load_context(conversation_id: int):
with pool.connection() as conn:
with conn.cursor() as cursor:
cursor.execute(
"""SELECT role, content, created_at
FROM agent_messages
WHERE conversation_id = %s
ORDER BY created_at""",
(conversation_id,),
)
return cursor.fetchall()
Gerenciadores de contexto fecham cursor e conexão mesmo após exceções. Passe dados pelos placeholders posicionais %s ou nomeados; nunca concatene entrada do usuário no SQL. Use fetchone para uma linha, fetchall apenas para conjuntos pequenos e itere pelo cursor para grandes volumes.
Contextos, parâmetros, , e pools do psycopg formam uma fronteira de aplicação mais segura.
16. Tratar falhas e otimizar o tráfego
Repita com recuo exponencial apenas OperationalError transitório causado por rede, reinicialização ou contenção temporária. Erros de sintaxe e violações de dados exigem correção. UniqueViolation, ForeignKeyViolation e CheckViolation devem gerar mensagem útil e . DeadlockDetected e LockNotAvailable podem ser repetidos após ; adquirir bloqueios sempre na mesma ordem reduz deadlocks.
Vazamentos esgotam o pool, portanto devolva toda conexão. Configure de conexão e instrução conforme o orçamento de latência. Use executemany para centenas ou poucos milhares de linhas e COPY para lotes maiores.
with cursor.copy(
"COPY agent_messages (conversation_id, role, content) FROM STDIN"
) as copy:
for message in messages:
copy.write_row(message)
Instruções preparadas reutilizam análise e plano. O pool evita , autenticação e alocação a cada operação. Dimensione-o com base na concorrência e no limite do servidor, não por um número arbitrariamente alto.
Resumo do tópico
Classifique o erro antes de repetir e reduza viagens com pool, lotes, instruções preparadas e COPY.
17. Laboratório guiado: de ferramentas do agente
O exercício de origem usa cerca de 30 minutos para construir um PostgreSQL que o agente acessa como ferramenta. Conversas e estado de tarefas continuam disponíveis após reinicializações e interrupções.
Prepare assinatura do com permissão de implantação, , a CLI do atual, Python 3.12 ou superior e psql.
Baixe o projeto inicial e parametrize a implantação.
Implante um servidor flexível do com autenticação do .
Crie tabelas de conversas, mensagens e checkpoints com relações e restrições.
Implemente funções Python para gravar mensagens, salvar checkpoints e recuperar contexto.
Execute o teste do fluxo e inspecione os dados com SQL.
Interrompa e retome uma tarefa para comprovar a memória entre sessões.
Exclua os recursos descartáveis ao terminar.
O padrão completo conecta identidade, pool, integridade do esquema, consultas e estado persistente.
Resumo do tópico
O laboratório comprova que tabelas PostgreSQL e ferramentas Python preservam conversa e checkpoints entre execuções.
18. Revisão da avaliação e checklist final
de conversa com estruturas variáveis: JSONB é flexível, consultável e indexável.
ID gerado necessário logo após inserir: RETURNING devolve o valor na mesma instrução.
Inserir ou atualizar preferência sem duplicar: INSERT ... ON CONFLICT DO UPDATE.
Muitas conexões Python curtas: ConnectionPool mantém conexões reutilizáveis.
Status limitado a um conjunto: CHECK (status IN (...)) impõe a regra.
As alternativas pertencem a outros bancos ou aplicam outra regra: VARCHAR(MAX), OUTPUT, LAST_INSERT_ID() e ON DUPLICATE KEY UPDATE não são respostas PostgreSQL; UNIQUE não limita valores possíveis; NOT NULL DEFAULT preenche, mas não rejeita outro status; uma única conexão global é frágil sob concorrência.
Dimensione computação e pool pela concorrência medida.
Use , verify-full e privilégio mínimo.
Mantenha fatos estáveis no relacional e variabilidade controlada no JSONB.
Indexe filtros, joins e ordenações sem indexar tudo.
Prefira paginação por chave, RETURNING e ON CONFLICT.
Use SQL parametrizado, ,, repetição seletiva e pool.
Um de IA pronto para produção combina operações gerenciadas, identidade e transporte seguros, esquema intencional, SQL eficiente e disciplina no cliente.