使用说明
🐘 Postgres MCP专家DBA
一个专门的MCP(模型上下文协议)服务器和Gradio UI,将您的本地LLM(通过Ollama)变成世界级的Postgres DBA。
特征
- 模式感知:AI会自动检查您的表和索引。
- 数据检查:执行只读查询以解决问题。
- 性能分析:使用分析查询执行计划
EXPLAIN ANALYZE. - 健康监测:检查数据库大小、活动连接和长时间运行的查询。
先决条件
- PostgreSQL:正在运行的实例(每个用户请求的默认端口5433)。
- 奥拉玛:已在本地安装并运行。
- 模型:下载请求的型号:
ollama pull gpt-oss:20b(或任何支持工具调用的模型,如llama3.1).
设置
-
安装依赖项:
pip install -r requirements.txt -
配置环境: 编辑
.env包含数据库凭据的文件:DB_PORT=5433 DB_USER=admin DB_PASSWORD=password DB_NAME=postgres DB_HOST=localhost OLLAMA_MODEL=gpt-oss:20b
运行应用程序
启动Gradio界面:
python3 app.py
该应用程序将于 http://localhost:7860.
用紫外线运行
uv run --with-requirements requirements.txt app.py
原理
server.py:使用实现MCP服务器FastMCP.app.py:充当MCP客户端和Gradio UI。它使用ollamaPython SDK与本地模型交互,编排对MCP服务器的工具调用。
现在,您可以提出以下问题:
-
我的数据库现在的健康状况如何?
-
你能列出所有数据库中的所有角色和权限吗
-
显示我最常用的表及其模式。
-
为什么以下查询需要这么长时间?[您的问题]
-
根据常见查询为“users”表建议索引策略。
-
我有什么桌子?
-
每个表有多少行?
-
我们是否有任何臃肿的表或性能问题?
-
为什么以下查询需要这么长时间?[资产估值为( 选择 p.user_id, SUM(p.quantities*a.current _ price)总计_资产值 来自投资组合p 加入资产a ON p.asset_id=a.asset_id 按p.user_id分组 ), 现金平衡AS( 选择 user_id, 总和(余额)为总现金 来自账户 货币=“美元” 按用户id分组 ) 选择 u.user_id, u.full_name, u.电子邮件, COALECE(c.total_cash,0)表示total_cash_usd, COALESCE(v.total_asset_value,0)作为total_portfolio_sd, (COALENCE(c.total_cash,0)+COALESCE(v.total_asset_value,0))作为total_net_vorth 来自用户u 左加入现金平衡c ON u.user_id=c.user_id 左加入资产估值v ON u.user_id=v.user_id 其中u.kyc_status=真 按总数排序_net_vorth DESC 限制100;]
-
你能为postgresworkshop模式中的索引提供建议吗。
Why is the following query taking so long? [SELECT
u.full_name,
u.email,
e.title,
e.event_date,
r.registration_date,
-- The Correlated Subquery (will now actually execute)
(
SELECT COUNT(*)
FROM registrations r2
JOIN events e2 ON r2.event_id = e2.event_id
WHERE r2.user_id = u.user_id
AND e2.category = e.category
AND r2.registration_id != r.registration_id
AND EXTRACT(MONTH FROM r2.registration_date) = EXTRACT(MONTH FROM r.registration_date)
) AS similar_monthly_registrations
FROM users u
JOIN registrations r ON u.user_id = r.user_id
JOIN events e ON r.event_id = e.event_id
WHERE
-- 1. Non-SARGable Date Math
EXTRACT(ISODOW FROM r.registration_date) = EXTRACT(ISODOW FROM e.event_date)
-- 2. Non-SARGable Date Differences
AND (r.registration_date::date - u.signup_date::date) > 100
-- 3. The FIXED String Match (Checks if the last digit of user_id is in the event title)
AND e.title ILIKE '%' || RIGHT(u.user_id::text, 1) || '%'
ORDER BY
-- 4. Sorting by the computed subquery
similar_monthly_registrations DESC,
e.event_date DESC
LIMIT 50;]# postgres-mcp-server-with-chat-client