
Byted Bytehouse Load Analyzer
- 2 installs
- 408 repo stars
- Updated August 3, 2026
- volcengine/agentkit-samples
Analyzes ByteHouse cluster load and resource usage, measures query throughput, and reports performance bottlenecks with optimization suggestions.
About
Analyzes load and resource usage on a ByteHouse cloud data warehouse cluster, covering CPU, memory, disk, QPS, table hotness, and bottlenecks. A developer uses it to monitor ByteHouse performance and generate resource-usage and optimization reports.
- Reports CPU, memory, disk, and query-throughput metrics for a ByteHouse cluster
- Depends on the bytehouse-mcp skill for cluster access and writes JSON reports to output/
Byted Bytehouse Load Analyzer by the numbers
- 2 all-time installs (skills.sh)
- Ranked #741 of 911 Databases skills by installs in the Skillselion catalog
- Data as of Aug 4, 2026 (Skillselion catalog sync)
npx skills add https://github.com/volcengine/agentkit-samples --skill byted-bytehouse-load-analyzerAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 2 |
|---|---|
| repo stars | ★ 408 |
| Last updated | August 3, 2026 |
| Repository | volcengine/agentkit-samples ↗ |
What it does
Analyzes ByteHouse cluster load and resource usage, measures query throughput, and reports performance bottlenecks with optimization suggestions.
Files
ByteHouse 负载分析 Skill
🔵 ByteHouse 品牌标识
「ByteHouse」—— 火山引擎云原生数据仓库,极速、稳定、安全、易用
>
本Skill基于ByteHouse MCP Server,提供完整的集群负载分析和性能监控能力
---
描述
ByteHouse集群负载分析和性能监控工具。
当以下情况时使用此 Skill: (1) 需要分析集群负载情况 (2) 需要监控资源使用情况 (3) 需要分析查询吞吐量 (4) 需要识别性能瓶颈 (5) 用户提到"负载分析"、"性能监控"、"资源使用"、"吞吐量"
前置条件
- Python 3.8+
- uv (已安装在
/root/.local/bin/uv) - ByteHouse MCP Server Skill - 本skill依赖
bytehouse-mcpskill提供的ByteHouse访问能力
依赖关系
本skill依赖 bytehouse-mcp skill,使用其提供的MCP Server访问ByteHouse。
确保 bytehouse-mcp skill已正确配置并可以正常使用。
📁 文件说明
- SKILL.md - 本文件,技能主文档
- load_analyzer.py - 负载分析主程序
- README.md - 快速入门指南
配置信息
ByteHouse连接配置
本skill复用 bytehouse-mcp skill的配置。请确保已在 bytehouse-mcp skill中配置好:
export BYTEHOUSE_HOST="<ByteHouse-host>"
export BYTEHOUSE_PORT="<ByteHouse-port>"
export BYTEHOUSE_USER="<ByteHouse-user>"
export BYTEHOUSE_PASSWORD="<ByteHouse-password>"
export BYTEHOUSE_SECURE="true"
export BYTEHOUSE_VERIFY="true"🎯 功能特性
1. 资源使用分析
- CPU使用率监控
- 内存使用率分析
- 磁盘空间监控
- 网络流量统计
2. 查询负载分析
- QPS (每秒查询数) 统计
- 查询并发度分析
- 查询类型分布
- 高峰时段识别
3. 表负载分析
- 表访问热度排名
- 表读写比例分析
- 表大小增长趋势
- 分区负载分布
4. 性能瓶颈识别
- 资源瓶颈识别
- 查询队列分析
- 锁等待统计
- 优化建议生成
🚀 快速开始
方法1: 运行负载分析
cd /root/.openclaw/workspace/skills/bytehouse-load-analyzer
# 先设置环境变量(复用bytehouse-mcp的配置)
export BYTEHOUSE_HOST="<ByteHouse-host>"
export BYTEHOUSE_PORT="<ByteHouse-port>"
export BYTEHOUSE_USER="<ByteHouse-user>"
export BYTEHOUSE_PASSWORD="<ByteHouse-password>"
export BYTEHOUSE_SECURE="true"
export BYTEHOUSE_VERIFY="true"
# 运行负载分析
uv run load_analyzer.py分析内容包括:
- 集群资源使用情况
- 查询负载统计
- 表访问热度
- 性能瓶颈识别
- 优化建议生成
输出文件(保存在 `output/` 目录): 1. `resource_usage_{timestamp}.json` - 资源使用报告 2. `query_load_{timestamp}.json` - 查询负载报告 3. `table_load_{timestamp}.json` - 表负载报告 4. `bottleneck_analysis_{timestamp}.json` - 瓶颈分析报告
💻 负载分析维度
资源维度
- CPU: 使用率、等待时间、上下文切换
- 内存: 使用量、缓存、Swap使用
- 磁盘: 使用率、IOPS、吞吐量
- 网络: 入流量、出流量、连接数
时间维度
- 实时: 当前负载情况
- 最近1小时: 1小时内趋势
- 最近24小时: 24小时内趋势
- 最近7天: 7天内趋势
- 历史对比: 同比环比分析
表维度
- 访问热度: 查询次数排名
- 读写比例: 读写操作比例
- 大小增长: 表大小变化趋势
- 分区分布: 分区数据分布
---
📊 负载报告示例
资源使用报告
{
"analysis_time": "2026-03-12T21:00:00",
"cluster_name": "bh_log_boe",
"resources": {
"cpu": {
"usage_percent": 65.5,
"wait_time_ms": 15,
"context_switches": 10000
},
"memory": {
"used_gb": 128.5,
"total_gb": 256.0,
"usage_percent": 50.2
},
"disk": {
"used_gb": 5120.0,
"total_gb": 10240.0,
"usage_percent": 50.0,
"iops_read": 5000,
"iops_write": 3000
}
}
}查询负载报告
{
"analysis_time": "2026-03-12T21:00:00",
"query_load": {
"qps": 500,
"concurrent_queries": 50,
"query_types": {
"SELECT": 70,
"INSERT": 20,
"UPDATE": 5,
"DELETE": 3,
"DDL": 2
},
"peak_hours": [
"10:00-11:00",
"14:00-15:00",
"20:00-21:00"
]
}
}---
📚 更多信息
详细使用说明请参考 bytehouse-mcp skill
--- 最后更新: 2026-03-12
# Copyright (c) 2025 Beijing Volcano Engine Technology Co., Ltd. and/or its affiliates.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.ByteHouse 负载分析 Skill
🔵 ByteHouse 品牌标识
「ByteHouse」—— 火山引擎云原生数据仓库,极速、稳定、安全、易用
>
本Skill基于ByteHouse MCP Server,提供完整的集群负载分析和性能监控能力
---
📁 文件说明
- SKILL.md - 技能主文档,包含详细使用说明
- load_analyzer.py - 负载分析主程序
- README.md - 本文件,快速入门指南
🎯 功能特性
1. 资源使用分析
- CPU使用率监控
- 内存使用率分析
- 磁盘空间监控
- 网络流量统计
2. 查询负载分析
- QPS (每秒查询数) 统计
- 查询并发度分析
- 查询类型分布
- 高峰时段识别
3. 表负载分析
- 表访问热度排名
- 表读写比例分析
- 表大小增长趋势
- 分区负载分布
4. 性能瓶颈识别
- 资源瓶颈识别
- 查询队列分析
- 锁等待统计
- 优化建议生成
🚀 快速开始
前置条件
本skill依赖 bytehouse-mcp skill,确保已正确配置:
cd /root/.openclaw/workspace/skills/bytehouse-mcp
# 确认bytehouse-mcp可以正常工作
uv run test_mcp_server.py方法1: 运行负载分析
cd /root/.openclaw/workspace/skills/bytehouse-load-analyzer
# 先设置环境变量(复用bytehouse-mcp的配置)
export BYTEHOUSE_HOST="<ByteHouse-host>"
export BYTEHOUSE_PORT="<ByteHouse-port>"
export BYTEHOUSE_USER="<ByteHouse-user>"
export BYTEHOUSE_PASSWORD="<ByteHouse-password>"
export BYTEHOUSE_SECURE="true"
export BYTEHOUSE_VERIFY="true"
# 运行负载分析
uv run load_analyzer.py分析内容包括:
- 集群资源使用情况
- 查询负载统计
- 表访问热度
- 性能瓶颈识别
- 优化建议生成
输出文件(保存在 `output/` 目录): 1. `resource_usage_{timestamp}.json` - 资源使用报告 2. `query_load_{timestamp}.json` - 查询负载报告 3. `table_load_{timestamp}.json` - 表负载报告 4. `bottleneck_analysis_{timestamp}.json` - 瓶颈分析报告
📚 更多信息
详细使用说明请参考 SKILL.md
ByteHouse访问配置请参考 bytehouse-mcp skill
--- 最后更新: 2026-03-12
#!/usr/bin/env python3
# Copyright (c) 2025 Beijing Volcano Engine Technology Co., Ltd. and/or its affiliates.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""
ByteHouse 负载分析工具
分析集群资源使用、查询负载、表负载等
"""
# /// script
# dependencies = [
# "mcp>=1.0.0",
# ]
# ///
import asyncio
import os
import json
from datetime import datetime, timedelta
from typing import Dict, List, Any
from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client
def is_cdw_environment():
"""检测是否为CDW环境
根据BYTEHOUSE_HOST判断:
- CDW: tenant-xxxx-cn-shanghai-public.bytehouse.volces.com
- CE: xxxx-public.bytehouse-ce.volces.com
"""
host = os.environ.get('BYTEHOUSE_HOST', '')
return '.bytehouse.volces.com' in host and '.bytehouse-ce.volces.com' not in host
def get_system_table_name(table_name):
"""根据环境返回正确的系统表名
"""
if is_cdw_environment():
table_mapping = {
'query_log': 'bh_system.query_log',
'processes': 'system.processes',
'parts': 'system.cnch_parts_info'
}
return table_mapping.get(table_name, table_name)
else:
return f'system.{table_name}'
def get_parts_table_columns():
"""根据环境返回parts表的正确字段名
"""
if is_cdw_environment():
# CDW system.cnch_parts_info 表字段
return {
'rows': 'total_rows_count',
'bytes': 'total_parts_size',
'active': 'ready_state',
'active_condition': "ready_state = 'Loaded'"
}
else:
# CE system.parts 表字段
return {
'rows': 'rows',
'bytes': 'bytes',
'active': 'active',
'active_condition': 'active'
}
async def run_load_analysis():
"""运行负载分析"""
print("=" * 80)
print("ByteHouse 负载分析工具")
print("=" * 80)
print()
print("⚠️ 请确保已设置以下环境变量:")
print(" - BYTEHOUSE_HOST")
print(" - BYTEHOUSE_PORT")
print(" - BYTEHOUSE_USER")
print(" - BYTEHOUSE_PASSWORD")
print()
# 从环境变量获取配置
env = os.environ.copy()
# MCP Server参数
server_params = StdioServerParameters(
command='/root/.local/bin/uvx',
args=[
'--from',
'git+https://github.com/volcengine/mcp-server@main#subdirectory=server/mcp_server_bytehouse',
'mcp_bytehouse',
'-t',
'stdio'
],
env=env
)
async with stdio_client(server_params) as (read, write):
async with ClientSession(read, write) as session:
await session.initialize()
print("✅ 连接成功!")
# 分析结果
analysis = {
"analysis_time": datetime.now().isoformat(),
"resource_usage": {},
"query_load": {},
"table_load": {},
"bottleneck_analysis": [],
"recommendations": []
}
# 1. 获取查询负载统计
print("\n1️⃣ 获取查询负载统计...")
try:
query_log_table = get_system_table_name('query_log')
if not query_log_table:
print(" ℹ️ 环境不支持查询日志表")
analysis["query_load"] = {
"time_range": "last_1_hour",
"stats": "Not supported in this environment"
}
else:
sql = f"""
SELECT
count(*) as query_count,
avg(query_duration_ms) as avg_duration_ms,
max(query_duration_ms) as max_duration_ms,
sum(read_rows) as total_read_rows,
sum(read_bytes) as total_read_bytes,
sum(written_rows) as total_written_rows,
sum(written_bytes) as total_written_bytes
FROM {query_log_table}
WHERE
type = 'QueryFinish'
AND event_time > now() - interval 1 hour
"""
result = await session.call_tool("run_select_query", {"query": sql})
query_load_data = []
for content in result.content:
if content.type == 'text':
query_load_data = content.text
analysis["query_load"] = {
"time_range": "last_1_hour",
"stats": query_load_data
}
print(" ✅ 成功获取查询负载统计")
except Exception as e:
print(f" ⚠️ 获取查询负载统计失败: {e}")
# 2. 获取表负载统计(基于parts表)
print("\n2️⃣ 获取表负载统计...")
try:
parts_table = get_system_table_name('parts')
if not parts_table:
print(" ℹ️ 环境不支持parts表")
analysis["table_load"] = {
"top_tables": "Not supported in this environment"
}
else:
parts_columns = get_parts_table_columns()
sql = f"""
SELECT
database,
table,
sum({parts_columns['rows']}) as total_rows,
sum({parts_columns['bytes']}) as total_bytes,
count(*) as part_count,
sum(if({parts_columns['active_condition']}, 1, 0)) as active_part_count
FROM {parts_table}
WHERE database != 'system'
GROUP BY database, table
ORDER BY total_bytes DESC
LIMIT 20
"""
result = await session.call_tool("run_select_query", {"query": sql})
table_load_data = []
for content in result.content:
if content.type == 'text':
table_load_data = content.text
analysis["table_load"] = {
"top_tables": table_load_data
}
print(" ✅ 成功获取表负载统计")
except Exception as e:
print(f" ⚠️ 获取表负载统计失败: {e}")
# 3. 获取QPS趋势(按分钟)
print("\n3️⃣ 获取QPS趋势...")
try:
query_log_table = get_system_table_name('query_log')
if not query_log_table:
print(" ℹ️ 环境不支持查询日志表")
analysis["query_load"]["qps_trend"] = "Not supported in this environment"
else:
sql = f"""
SELECT
toStartOfMinute(event_time) as time_bucket,
count(*) as qps
FROM {query_log_table}
WHERE
type = 'QueryFinish'
AND event_time > now() - interval 1 hour
GROUP BY time_bucket
ORDER BY time_bucket DESC
LIMIT 60
"""
result = await session.call_tool("run_select_query", {"query": sql})
qps_trend_data = []
for content in result.content:
if content.type == 'text':
qps_trend_data = content.text
analysis["query_load"]["qps_trend"] = qps_trend_data
print(" ✅ 成功获取QPS趋势")
except Exception as e:
print(f" ⚠️ 获取QPS趋势失败: {e}")
# 4. 获取当前正在执行的查询
print("\n4️⃣ 获取当前正在执行的查询...")
try:
processes_table = get_system_table_name('processes')
if processes_table:
# CE和CDW都使用system.processes表
sql = f"""
SELECT
query_id,
query,
elapsed,
read_rows,
read_bytes
FROM {processes_table}
LIMIT 10
"""
result = await session.call_tool("run_select_query", {"query": sql})
current_queries_data = []
for content in result.content:
if content.type == 'text':
current_queries_data = content.text
analysis["query_load"]["current_queries"] = current_queries_data
print(" ✅ 成功获取当前查询")
else:
print(" ℹ️ 环境不支持获取当前查询")
analysis["query_load"]["current_queries"] = "Not supported in this environment"
except Exception as e:
print(f" ⚠️ 获取当前查询失败: {e}")
# 5. 生成负载分析和建议
print("\n5️⃣ 生成负载分析和建议...")
recommendations = []
recommendations.append({
"type": "monitoring",
"priority": "high",
"title": "持续监控查询负载",
"description": "建议设置监控告警,关注QPS和查询延迟变化",
"action": "配置Grafana或类似监控工具,实时监控查询性能"
})
recommendations.append({
"type": "resource",
"priority": "medium",
"title": "资源扩容评估",
"description": "根据表大小增长趋势,评估是否需要扩容存储",
"action": "定期检查表大小增长率,规划容量"
})
recommendations.append({
"type": "optimization",
"priority": "medium",
"title": "查询优化",
"description": "分析Top N慢查询,进行针对性优化",
"action": "使用慢查询分析工具,识别性能瓶颈"
})
recommendations.append({
"type": "partition",
"priority": "low",
"title": "分区优化",
"description": "检查表分区策略,考虑更细粒度的分区",
"action": "评估分区键选择,优化查询性能"
})
analysis["recommendations"] = recommendations
print(f" ✅ 生成了 {len(recommendations)} 条建议")
# 6. 瓶颈分析
bottleneck_analysis = []
bottleneck_analysis.append({
"type": "query_pattern",
"description": "检查是否有热点查询模式",
"status": "needs_analysis"
})
bottleneck_analysis.append({
"type": "table_size",
"description": "监控大表增长趋势",
"status": "needs_monitoring"
})
bottleneck_analysis.append({
"type": "resource_usage",
"description": "评估CPU、内存、磁盘使用情况",
"status": "needs_monitoring"
})
analysis["bottleneck_analysis"] = bottleneck_analysis
print(f" ✅ 完成瓶颈分析")
# 保存分析结果
output_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), "output")
os.makedirs(output_dir, exist_ok=True)
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
output_file = os.path.join(output_dir, f"load_analysis_{timestamp}.json")
with open(output_file, "w", encoding="utf-8") as f:
json.dump(analysis, f, ensure_ascii=False, indent=2)
# 打印分析摘要
print("\n" + "=" * 80)
print("📊 负载分析摘要")
print("=" * 80)
print(f"\n分析时间: {analysis['analysis_time']}")
print(f"\n瓶颈分析: {len(analysis['bottleneck_analysis'])} 项")
print(f"\n优化建议: {len(analysis['recommendations'])} 条")
print(f"\n前3条建议:")
for i, rec in enumerate(analysis['recommendations'][:3], 1):
print(f" {i}. [{rec['priority'].upper()}] {rec['title']}")
print(f" {rec['description']}")
print(f"\n📁 分析报告已保存到: {output_file}")
print("\n" + "=" * 80)
async def main():
"""主函数"""
try:
await run_load_analysis()
print("\n✅ 负载分析完成!")
except Exception as e:
print(f"\n❌ 负载分析失败: {e}")
import traceback
traceback.print_exc()
if __name__ == "__main__":
asyncio.run(main())