perf: 记账失败列表优化

- 去掉跨库JOIN,改用内存批量ID映射
- 不查failed_reason大TEXT字段
- handled状态直接后台转文本,前端不依赖data映射
This commit is contained in:
yumoqing 2026-06-26 17:08:58 +08:00
parent 329260435c
commit a6efef56e9
2 changed files with 74 additions and 66 deletions

View File

@ -16,10 +16,6 @@ try:
filters['start_date'] = params_kw.get('start_date') filters['start_date'] = params_kw.get('start_date')
if params_kw.get('end_date'): if params_kw.get('end_date'):
filters['end_date'] = params_kw.get('end_date') filters['end_date'] = params_kw.get('end_date')
if params_kw.get('filter_userid'):
filters['filter_userid'] = params_kw.get('filter_userid')
if params_kw.get('filter_llmid'):
filters['filter_llmid'] = params_kw.get('filter_llmid')
try: try:
page = int(params_kw.get('page', 1)) page = int(params_kw.get('page', 1))
@ -34,52 +30,37 @@ try:
ns = {} ns = {}
if filters.get('userorgid'): if filters.get('userorgid'):
conditions.append("f.userorgid=${userorgid}$") conditions.append("userorgid=${userorgid}$")
ns['userorgid'] = filters['userorgid'] ns['userorgid'] = filters['userorgid']
if filters.get('llmid'): if filters.get('llmid'):
conditions.append("f.llmid=${llmid}$") conditions.append("llmid=${llmid}$")
ns['llmid'] = filters['llmid'] ns['llmid'] = filters['llmid']
if filters.get('handled') is not None: if filters.get('handled') is not None:
conditions.append("f.handled=${handled}$") conditions.append("handled=${handled}$")
ns['handled'] = filters['handled'] ns['handled'] = filters['handled']
if filters.get('start_date'): if filters.get('start_date'):
conditions.append("f.use_date>=${start_date}$") conditions.append("use_date>=${start_date}$")
ns['start_date'] = filters['start_date'] ns['start_date'] = filters['start_date']
if filters.get('end_date'): if filters.get('end_date'):
conditions.append("f.use_date<=${end_date}$") conditions.append("use_date<=${end_date}$")
ns['end_date'] = filters['end_date'] ns['end_date'] = filters['end_date']
if filters.get('filter_userid'):
conditions.append("(u.username LIKE ${filter_userid}$ OR u.name LIKE ${filter_userid}$)")
ns['filter_userid'] = '%' + filters['filter_userid'] + '%'
if filters.get('filter_llmid'):
conditions.append("(f.llmid LIKE ${filter_llmid}$ OR l.name LIKE ${filter_llmid}$)")
ns['filter_llmid'] = '%' + filters['filter_llmid'] + '%'
where = "" where = ""
if conditions: if conditions:
where = "WHERE " + " AND ".join(conditions) where = "WHERE " + " AND ".join(conditions)
# 跨库JOIN获取名称 # 不查 failed_reason大 TEXT只查列表需要的字段
sql = f""" sql = f"""
SELECT f.id, f.llmusageid, f.llmid, f.userid, f.userorgid, f.use_date, f.use_time, SELECT id, llmusageid, llmid, userid, userorgid, use_date, use_time,
f.amount, f.cost, f.failed_reason, f.failed_time, f.retry_count, f.handled, amount, cost, failed_time, retry_count, handled
u.username as userid_text, FROM llmusage_accounting_failed
o.orgname as userorgid_text,
l.name as llmid_text
FROM llmusage_accounting_failed f
LEFT JOIN {sage_db}.users u ON f.userid = u.id
LEFT JOIN {sage_db}.organization o ON f.userorgid = o.id
LEFT JOIN {llmage_db}.llm l ON f.llmid = l.id
{where} {where}
ORDER BY f.failed_time DESC ORDER BY failed_time DESC
""" """
count_sql = f""" count_sql = f"""
SELECT count(*) as cnt SELECT count(*) as cnt
FROM llmusage_accounting_failed f FROM llmusage_accounting_failed
LEFT JOIN {sage_db}.users u ON f.userid = u.id
LEFT JOIN {sage_db}.organization o ON f.userorgid = o.id
LEFT JOIN {llmage_db}.llm l ON f.llmid = l.id
{where} {where}
""" """
count_recs = await sor.sqlExe(count_sql, ns) count_recs = await sor.sqlExe(count_sql, ns)
@ -89,16 +70,60 @@ LEFT JOIN {llmage_db}.llm l ON f.llmid = l.id
query_sql = sql + f" LIMIT {page_size} OFFSET {offset}" query_sql = sql + f" LIMIT {page_size} OFFSET {offset}"
recs = await sor.sqlExe(query_sql, ns) recs = await sor.sqlExe(query_sql, ns)
rows = [] if recs:
for r in (recs or []): # 收集所有需要转换的 ID
d = dict(r) llm_ids = list(set(r.llmid for r in recs if r.llmid))
rows.append(d) user_ids = list(set(r.userid for r in recs if r.userid))
org_ids = list(set(r.userorgid for r in recs if r.userorgid))
result['rows'] = rows # 批量查询映射(内存中完成)
result['total'] = total llm_map = {}
result['page'] = page if llm_ids:
result['page_size'] = page_size llm_recs = await sor.sqlExe(
result['success'] = True "SELECT id, name FROM llm WHERE id IN ${ids}$",
{'ids': tuple(llm_ids)}
)
if llm_recs:
llm_map = {r.id: r.name for r in llm_recs}
user_map = {}
if user_ids:
async with db.sqlorContext(sage_db) as sage_sor:
user_recs = await sage_sor.sqlExe(
"SELECT id, username FROM users WHERE id IN ${ids}$",
{'ids': tuple(user_ids)}
)
if user_recs:
user_map = {r.id: r.username for r in user_recs}
org_map = {}
if org_ids:
async with db.sqlorContext(sage_db) as sage_sor:
org_recs = await sage_sor.sqlExe(
"SELECT id, orgname FROM organization WHERE id IN ${ids}$",
{'ids': tuple(org_ids)}
)
if org_recs:
org_map = {r.id: r.orgname for r in org_recs}
# 转换
handled_map = {'0': '未处理', '1': '已处理'}
rows = []
for r in recs:
d = dict(r)
d['llmid_text'] = llm_map.get(r.llmid, r.llmid)
d['userid_text'] = user_map.get(r.userid, r.userid)
d['userorgid_text'] = org_map.get(r.userorgid, r.userorgid)
d['handled_text'] = handled_map.get(r.handled, r.handled)
rows.append(d)
result['rows'] = rows
result['total'] = total
result['page'] = page
result['page_size'] = page_size
result['success'] = True
else:
result['success'] = True
except Exception as e: except Exception as e:
result['error'] = str(e) result['error'] = str(e)

View File

@ -69,8 +69,7 @@
"id", "id",
"failed_reason" "failed_reason"
], ],
"alters": { "alters": {}
}
}, },
"fields": [ "fields": [
{ {
@ -83,36 +82,30 @@
"label": "使用记录ID" "label": "使用记录ID"
}, },
{ {
"name": "llmid", "name": "llmid_text",
"title": "模型", "title": "模型",
"type": "str", "type": "str",
"length": 32, "length": 32,
"cwidth": 12, "cwidth": 12,
"uitype": "code", "uitype": "str",
"textField": "llmid_text",
"valueField": "llmid",
"label": "模型" "label": "模型"
}, },
{ {
"name": "userid", "name": "userid_text",
"title": "用户", "title": "用户",
"type": "str", "type": "str",
"length": 32, "length": 32,
"cwidth": 10, "cwidth": 10,
"uitype": "code", "uitype": "str",
"valueField": "userid",
"textField": "userid_text",
"label": "用户" "label": "用户"
}, },
{ {
"name": "userorgid", "name": "userorgid_text",
"title": "机构", "title": "机构",
"type": "str", "type": "str",
"length": 32, "length": 32,
"cwidth": 10, "cwidth": 10,
"uitype": "code", "uitype": "str",
"valueField": "userorgid",
"textField": "userorgid_text",
"label": "机构" "label": "机构"
}, },
{ {
@ -158,22 +151,12 @@
"label": "重试" "label": "重试"
}, },
{ {
"name": "handled", "name": "handled_text",
"title": "状态", "title": "状态",
"type": "str", "type": "str",
"length": 1, "length": 1,
"cwidth": 6, "cwidth": 6,
"uitype": "code", "uitype": "str",
"data": [
{
"value": "0",
"text": "未处理"
},
{
"value": "1",
"text": "已处理"
}
],
"label": "状态" "label": "状态"
} }
] ]