优化 llmusage CRUD 查询性能
- 新建 api/llmusage_list.dspy 替代自动生成的 get_llmusage.dspy - 排除 usages/ioinfo 大 TEXT 字段过滤,避免 LIKE 全表扫描 - 分离 count/data 查询,避免 sqlPaging 子查询包装 - 更新 json/llmusage.json get_data_url 指向新脚本 - 更新 scripts/load_path.py 注册新路径
This commit is contained in:
parent
3d1032c73b
commit
d58b86a704
@ -50,12 +50,20 @@
|
||||
}
|
||||
],
|
||||
"browserfields": {
|
||||
"exclouded": ["id", "usages", "ioinfo"],
|
||||
"exclouded": [
|
||||
"id",
|
||||
"usages",
|
||||
"ioinfo"
|
||||
],
|
||||
"alters": {}
|
||||
},
|
||||
"editexclouded": ["id", "usages", "ioinfo"],
|
||||
"editexclouded": [
|
||||
"id",
|
||||
"usages",
|
||||
"ioinfo"
|
||||
],
|
||||
"editable": {
|
||||
"get_data_url": "{{entire_url('get_llmusage.dspy')}}?pagerows=50",
|
||||
"get_data_url": "{{entire_url('../api/llmusage_list.dspy')}}?pagerows=50",
|
||||
"new_data_url": "{{entire_url('../api/llmusage_create.dspy')}}",
|
||||
"update_data_url": "{{entire_url('../api/llmusage_update.dspy')}}",
|
||||
"delete_data_url": "{{entire_url('../api/llmusage_delete.dspy')}}"
|
||||
|
||||
@ -157,6 +157,7 @@ PATHS_LOGINED = [
|
||||
f"/{MOD}/llmusage/update_llmusage.dspy",
|
||||
f"/{MOD}/llmusage_usages_display.dspy",
|
||||
f"/{MOD}/llmusage_ioinfo_display.dspy",
|
||||
f"/{MOD}/api/llmusage_list.dspy",
|
||||
|
||||
# CRUD 子目录 — llmusage_accounting_failed/
|
||||
f"/{MOD}/llmusage_accounting_failed/index.ui",
|
||||
|
||||
96
wwwroot/api/llmusage_list.dspy
Normal file
96
wwwroot/api/llmusage_list.dspy
Normal file
@ -0,0 +1,96 @@
|
||||
result = {'success': False, 'rows': [], 'total': 0, 'page': 1, 'page_size': 50}
|
||||
|
||||
try:
|
||||
ns = params_kw.copy()
|
||||
|
||||
if not ns.get('page'):
|
||||
ns['page'] = 1
|
||||
if not ns.get('sort'):
|
||||
ns['sort'] = 'use_time desc'
|
||||
|
||||
filterjson = params_kw.get('data_filter')
|
||||
if filterjson and isinstance(filterjson, str):
|
||||
try:
|
||||
filterjson = json.loads(filterjson)
|
||||
except (json.JSONDecodeError, TypeError):
|
||||
filterjson = None
|
||||
|
||||
fields_str=r'''[
|
||||
{"name": "id", "title": "id", "type": "str", "length": 32},
|
||||
{"name": "llmid", "title": "模型id", "type": "str", "length": 32},
|
||||
{"name": "use_date", "title": "使用日期", "type": "date"},
|
||||
{"name": "use_time", "title": "使用时间", "type": "timestamp"},
|
||||
{"name": "userid", "title": "用户id", "type": "str", "length": 32},
|
||||
{"name": "usages", "title": "使用信息", "type": "text"},
|
||||
{"name": "ioinfo", "title": "交互内容", "type": "text"},
|
||||
{"name": "transno", "title": "交易号", "type": "str", "length": 32},
|
||||
{"name": "responsed_seconds", "title": "响应时间", "type": "float", "length": 18, "dec": 2},
|
||||
{"name": "finish_seconds", "title": "结束时间", "type": "float", "length": 18, "dec": 2},
|
||||
{"name": "status", "title": "状态", "type": "str", "length": 32},
|
||||
{"name": "taskid", "title": "任务号", "type": "str", "length": 256},
|
||||
{"name": "amount", "title": "交易金额", "type": "float", "length": 18, "dec": 2},
|
||||
{"name": "cost", "title": "交易成本", "type": "float", "length": 18, "dec": 2},
|
||||
{"name": "userorgid", "title": "用户机构id", "type": "str", "length": 32},
|
||||
{"name": "ownerid", "title": "模型机构id", "type": "str", "length": 32},
|
||||
{"name": "accounting_status", "title": "记账状态", "type": "str", "length": 32}
|
||||
]'''
|
||||
ori_fields = json.loads(fields_str)
|
||||
|
||||
filterdic = ns.copy()
|
||||
filterdic['filterstr'] = ''
|
||||
filterdic['userorgid'] = '${userorgid}$'
|
||||
filterdic['userid'] = '${userid}$'
|
||||
|
||||
if not filterjson:
|
||||
# 排除大 TEXT 字段,避免生成 LIKE 过滤导致全表扫描
|
||||
filter_fields = [f['name'] for f in ori_fields if f['name'] not in ('usages', 'ioinfo')]
|
||||
filterjson = default_filterjson(filter_fields, ns)
|
||||
|
||||
if filterjson:
|
||||
dbf = DBFilter(filterjson)
|
||||
conds = dbf.gen(ns)
|
||||
if conds:
|
||||
ns.update(dbf.consts)
|
||||
conds = f' and {conds}'
|
||||
filterdic['filterstr'] = conds
|
||||
|
||||
ac = ArgsConvert('[[', ']]')
|
||||
sql_template = 'select id, llmid, use_date, use_time, userid, transno, responsed_seconds, finish_seconds, status, taskid, amount, cost, userorgid, ownerid, accounting_status from llmusage where 1=1 [[filterstr]]'
|
||||
vars = ac.findAllVariables(sql_template)
|
||||
NameSpace = {v: '${' + v + '}$' for v in vars if v != 'filterstr'}
|
||||
filterdic.update(NameSpace)
|
||||
where_sql = ac.convert(sql_template, filterdic)
|
||||
|
||||
# 提取 WHERE 条件,避免 sqlPaging 子查询包装
|
||||
idx = where_sql.lower().find('where')
|
||||
where_clause = where_sql[idx:] if idx >= 0 else 'where 1=1'
|
||||
|
||||
sort_field = ns.get('sort', 'use_time desc')
|
||||
|
||||
db = DBPools()
|
||||
dbname = get_module_dbname('llmage')
|
||||
|
||||
async with db.sqlorContext(dbname) as sor:
|
||||
# 分离 count 和 data 查询,避免子查询包装
|
||||
count_sql = f'select count(*) as rcnt from llmusage {where_clause}'
|
||||
count_recs = await sor.sqlExe(count_sql, ns)
|
||||
total = count_recs[0].rcnt if count_recs else 0
|
||||
|
||||
page = int(ns.get('page', 1))
|
||||
rows_per_page = int(ns.get('rows', ns.get('pagerows', 50)))
|
||||
offset = (page - 1) * rows_per_page
|
||||
|
||||
data_sql = f'select id, llmid, use_date, use_time, userid, transno, responsed_seconds, finish_seconds, status, taskid, amount, cost, userorgid, ownerid, accounting_status from llmusage {where_clause} order by {sort_field} limit {rows_per_page} offset {offset}'
|
||||
rows = await sor.sqlExe(data_sql, ns)
|
||||
|
||||
result['success'] = True
|
||||
result['total'] = total
|
||||
result['rows'] = rows if rows else []
|
||||
result['page'] = page
|
||||
result['page_size'] = rows_per_page
|
||||
|
||||
except Exception as e:
|
||||
debug(f'error: {traceback.format_exc()}')
|
||||
result['error'] = str(e)
|
||||
|
||||
return result
|
||||
Loading…
x
Reference in New Issue
Block a user