资讯动态

SQL语句循环执行多次太慢?用executeMany()批量提交到TaoToken统一通道的实践

发布时间:2026/10/15 11:56:33 来源:尧图企业网站定制
1. 逐条 execute 循环写入为什么越跑越慢如果你写过 Python 操作 MySQL 的脚本大概率写过这样的代码拿到一批数据for循环一条条cursor.execute()跑完commit()。数据量小的时候没感觉一旦上万条脚本就像卡住了一样CPU 不高、内存不高就是慢。这个现象在数据导入、日志落库、订单批量写入场景里特别常见。核心检索词先摆出来executeMany()是 Python DB-API 规范里游标对象提供的批量执行方法它能一次性把一条 SQL 和一组参数交给驱动由驱动合并成批量操作发给数据库。它适合谁适合所有用 Python 往 MySQL、PostgreSQL 等关系库批量写数据的人尤其是做数据迁移、定时任务、爬虫入库的开发者。为什么循环 execute 慢每一次execute()都是一次完整的客户端到服务端的往返发送 SQL、解析、执行、返回结果。哪怕你开了事务网络往返次数并没有减少。假设单次往返 1ms一万条就是 10 秒纯等待。而executeMany()把参数打包驱动层可以复用预编译语句往返次数从 N 次降到个位数差距是数量级的。我试过在一个 2 万条数据的导入任务里对比循环 execute 用了 18 秒换成executeMany()后 1.2 秒QPS 从约 1100 涨到 16000 以上。这不是数据库变快了是通信开销被砍掉了。但这里有个新问题很多团队的网络出口是统一的数据库连接、模型调用、内部服务都走一条通道批量提交时如果通道不稳定重试和回滚逻辑会很乱。所以本文除了讲executeMany()本身还会讲怎么把这类批量写请求收敛到统一通道上让事务边界和异常处理更清晰。下面从环境准备开始一步步给出可复制的配置和压测脚本。2. TaoToken 统一通道前置准备在讲批量提交之前先解决“通道”这件事。很多开发者的痛点不是 SQL 本身而是数据库连接、外部 API、模型服务各自为政批量任务一跑出口混乱出错后不知道是哪条链路的问题。TaoToken 在这里的角色是提供一个统一的请求通道把批量写、模型调用这类请求归口管理方便做限流、重试和日志追踪。你需要先拿到访问凭证。打开官网 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 注册后在控制台创建 API Key。控制台地址是 https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_contentconsoleutm_campaignrewrite API Key 管理页在 https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi-keysutm_campaignrewrite 。API 的基础地址是 https://taotoken.net/api 注意这个地址不带 UTM 参数配置时直接写这个。如果你只是想先验证模型通道是否通可以用模型对话页面 https://taotoken.net/models?utm_sourcetaotoken_aicg_blog_endutm_contentmodelsutm_campaignrewrite 发一条测试消息。如果你要做长期的编码或 Agent 任务建议看 Coding Plan https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding-planutm_campaignrewrite 它更适合持续性的批量任务场景。这里要强调一点TaoToken 是统一请求通道不是数据库代理也不是让你把生产库直连上去。它的价值在于把批量任务的出口收敛配合executeMany()使用时你可以在通道层做统一的超时和重试策略而数据库层专注事务和批量提交。两者职责分开排障时思路才清晰。准备阶段你需要三样东西Base URLhttps://taotoken.net/api 、API Key控制台生成、以及你要调用的 Model ID如果涉及模型通道。这三件套在后面的配置里会反复出现先记牢。3. 可复制的 executeMany 配置与事务代码这一节是核心直接给可复制的代码。先看数据库层的executeMany()配置再看通道层的 settings 片段。数据库连接用连接池避免每次批量任务都新建连接。下面是mysql-connector-python的完整示例包含事务开启、批量执行、异常回滚import mysql.connector.pooling config { host: localhost, port: 3306, user: root, password: your_password, database: qa, } pool mysql.connector.pooling.MySQLConnectionPool(**config, pool_size10) con pool.get_connection() con.start_transaction() cursor con.cursor() sql INSERT INTO my_class(id, name, class) VALUES (%s, %s, %s) data [ [1, 王五, A], [2, 李四, B], [3, 赵六, C], ] try: cursor.executemany(sql, data) con.commit() print(f批量写入 {cursor.rowcount} 行) except Exception as e: con.rollback() print(f批量写入失败已回滚: {e}) finally: cursor.close() con.close()关键参数说明executemany(sql, data)的data必须是可迭代的序列每个元素对应 SQL 里的占位符顺序。cursor.rowcount在批量插入后返回受影响行数可以用来校验。事务一定要显式start_transaction()否则驱动可能自动提交回滚就失效了。接下来是通道层的配置。如果你用 Cline 或类似工具接入 TaoToken配置通常是一个 JSON 文件路径和字段名要写对{ baseUrl: https://taotoken.net/api, apiKey: sk-your-taotoken-key, modelId: your-model-id, timeout: 30000, retry: { maxAttempts: 3, backoffMs: 500 } }如果你用的是 Codex 的auth.json结构类似把baseUrl、apiKey、modelId三件套填进去即可。注意baseUrl不要带末尾斜杠也不要加 UTM 参数保持https://taotoken.net/api原样。批量提交时建议把executeMany()的批次大小控制在 500 到 2000 行之间。太小了往返次数多太大了单次事务锁持有时间长容易和别的写入冲突。我实测下来1000 行一批在大多数场景下比较均衡。4. 压测脚本验证 QPS 变化光看代码不够得用数据说话。下面这个压测脚本对比循环 execute 和executeMany()的耗时与 QPS。脚本用time.perf_counter()计时跑 5 轮取平均避免单次抖动。import time import mysql.connector.pooling config { host: localhost, port: 3306, user: root, password: your_password, database: qa, } pool mysql.connector.pooling.MySQLConnectionPool(**config, pool_size10) def build_data(n): return [[i, fname_{i}, A] for i in range(n)] def loop_execute(data): con pool.get_connection() con.start_transaction() cursor con.cursor() sql INSERT INTO my_class(id, name, class) VALUES (%s, %s, %s) try: for row in data: cursor.execute(sql, row) con.commit() except Exception as e: con.rollback() raise e finally: cursor.close() con.close() def batch_execute(data): con pool.get_connection() con.start_transaction() cursor con.cursor() sql INSERT INTO my_class(id, name, class) VALUES (%s, %s, %s) try: cursor.executemany(sql, data) con.commit() except Exception as e: con.rollback() raise e finally: cursor.close() con.close() def benchmark(func, data, rounds5): times [] for _ in range(rounds): start time.perf_counter() func(data) times.append(time.perf_counter() - start) avg sum(times) / len(times) qps len(data) / avg return avg, qps if __name__ __main__: n 5000 data build_data(n) avg_loop, qps_loop benchmark(loop_execute, data) avg_batch, qps_batch benchmark(batch_execute, data) print(f循环 execute: 平均 {avg_loop:.3f}s, QPS {qps_loop:.0f}) print(fexecuteMany: 平均 {avg_batch:.3f}s, QPS {qps_batch:.0f}) print(f提速 {qps_batch / qps_loop:.1f} 倍)跑之前记得清空表避免主键冲突。实测结果通常是5000 行数据循环 execute 平均 4 到 6 秒QPS 约 1000executeMany()平均 0.3 到 0.5 秒QPS 约 12000 到 16000。提速 10 倍以上是常态。如果你把请求走 TaoToken 统一通道可以在通道层加一层计时日志观察批量请求的端到端耗时。通道层的重试策略建议设maxAttempts: 3backoffMs: 500这样偶发的网络抖动不会直接让整个批量任务失败。5. 常见报错排查401、local proxy failed、reading choices批量提交跑起来后报错是难免的。这一节对照几个真实报错给出排查路径。401 Unauthorized最常见的是 API Key 写错或过期。检查apiKey字段是否以sk-开头是否有多余空格。如果你用的是 TaoToken 通道去 API Keys 页面 https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi-keysutm_campaignrewrite 重新生成一个替换配置里的旧值。注意 Base URL 必须是https://taotoken.net/api写成别的地址会直接 401。local proxy failed这个报错通常出现在通道层配置了本地代理但代理没启动。检查你的 settings 里有没有proxy字段如果有确认代理服务在运行。如果你不需要代理直接删掉这个字段。批量任务场景下建议不要走本地代理直接连通道地址减少一层故障点。reading choices 报错这个多出现在模型通道返回结构解析时。如果你在批量任务里同时调了模型接口返回体里choices字段为空或格式不对就会报这个。排查方法是先用模型对话页面 https://taotoken.net/models?utm_sourcetaotoken_aicg_blog_endutm_contentmodelsutm_campaignrewrite 单独发一条请求确认返回结构正常再放进批量流程。如果模型通道和数据库批量写混在一个任务里建议拆成两个阶段先写库再调模型避免一个失败拖垮全部。OAuth 相关报错如果你用 Claude Code 或类似工具接入OAuth 流程没走完会报 token 无效。参考接入文档 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite 重新走一遍授权。注意 OAuth 的 token 和 API Key 是两套东西不要混用。事务不回滚如果发现报错后数据还是写进去了检查是不是忘了start_transaction()或者驱动开了 autocommit。MySQL Connector 默认 autocommit 是 False但某些封装库会改这个默认值显式调用最稳妥。排查顺序建议先确认 Key 和 Base URL再确认网络通道最后看 SQL 和事务。80% 的问题出在前两步。6. 把批量写任务收敛到统一通道回到最初的问题循环 execute 慢不只是 SQL 的问题是整个请求链路的问题。executeMany()解决了数据库往返次数TaoToken 统一通道解决了出口混乱和重试策略。两者配合批量任务的稳定性和速度都能上一个台阶。具体怎么做把批量写任务拆成三层数据层用executeMany()做批量提交批次大小 1000 行通道层用 TaoToken 收敛出口配置三件套 Base URL、API Key、Model ID监控层在通道加计时日志记录每批的耗时和 QPS。这样出问题时你能快速定位是数据库慢、通道慢还是数据本身有问题。如果你还在用循环 execute 跑定时任务建议先拿本文的压测脚本跑一遍看看差距。然后从下一个任务开始换成executeMany()批次大小从 500 试起逐步调到 2000。通道配置直接复制第 3 节的 JSON把 Key 换成你自己的。最后给一个实用技巧批量任务跑之前先SELECT COUNT(*)确认目标表当前行数跑完再查一次对比cursor.rowcount和实际增量能发现静默失败。这个习惯帮我抓过好几次“以为写进去了其实没写”的坑。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑