ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

MySQL优化全攻略:索引、SQL与分库分表的最佳实践脑——用TaoToken统一Key跑通压测与慢查询验证

MySQL优化全攻略:索引、SQL与分库分表的最佳实践脑——用TaoToken统一Key跑通压测与慢查询验证 1. 电商订单库的慢查询与分片验证场景MySQL 优化这件事真正难的不是背索引八股而是把「索引设计、SQL 改写、分库分表」这三件事串成一条可验证的链路。我拿一个电商订单库举例订单主表t_order单表 8000 万行日增 200 万查询侧既有「按用户查最近订单」也有「按商家状态分页」还有运营后台的「按时间范围聚合」。上线分片之前慢查询日志一天能刷出几百条EXPLAIN里typeALL、rows动辄千万级。这个场景的核心检索词就是 MySQL 索引优化、SQL 改写、分库分表性能验证。它适合谁适合已经写过 CRUD、但一遇到「分片后 QPS 没涨反降」「加了索引还是走全表」就卡住的后端同学。你要做的不是重装数据库而是搭一条「采集慢查询 → EXPLAIN 对比 → 分片键选择 → 压测验证」的闭环中间用 TaoToken 的统一 Key 调模型帮你出索引建议和改写方案最后用 QPS 和扫描行数说话。我试过的坑是很多人分完表就不管了结果跨分片查询把IN拆成 N 个单分片查询扫描行数没降网络往返翻倍。所以验证环节必须量化不能靠感觉。下面按步骤走每一步都给可复制的配置和命令。先明确目标指标优化前t_order按user_id查询平均扫描 120 万行、QPS 约 380目标是扫描行数降到千级、QPS 提到 2000 以上。分片方案选user_id取模 8 库 64 表因为绝大多数高频查询都带user_id能保证单分片路由。2. TaoToken 统一 Key 的前置准备为什么要在这里引入 TaoToken因为优化过程中你会反复需要「根据慢 SQL 生成索引建议」「把子查询改写成 JOIN」「判断分片键是否合理」这类模型辅助。如果每个模型单独申请 Key、单独配 Base URL脚本里会散落一堆凭证压测和验证脚本没法统一管理。TaoToken 提供的是统一 Key / API 通道一个 Key 走https://taotoken.net/api模型 ID 按需切换脚本里只维护一份配置。前置准备分三步。第一步拿到 Key进入控制台创建 API Key地址是https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content创建后复制保存后面所有脚本都用它。第二步确认接入文档里的 Base URL 和请求格式文档入口https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content重点看 chat completions 的路径和鉴权头。第三步如果你用 Claude Code 这类编码工具做 SQL 改写可以走https://taotoken.net/claude-code-anthropic?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content看接入方式如果是长期跑 Agent 做批量 SQL 分析考虑 Coding Plan入口https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content。这里必须写全三件套缺一个都调不通Base URL 填https://taotoken.net/apiKey 填你刚创建的Model ID 按任务选比如做 SQL 改写用claude-sonnet-4-5或gpt-4o这类具体以文档里的模型列表为准。我实测下来把这三件套写进一个.env文件Python 脚本和 curl 都能复用比散落在各处强太多。注意TaoToken 是模型 API 通道不是数据库代理别把它当成 MySQL 中间件。它的作用是「你喂慢 SQL 和表结构它返回索引建议和改写 SQL」执行仍然在你的 MySQL 上。3. 可复制的慢查询采集与模型调用配置这一节给可直接落地的配置。先开慢查询日志MySQL 配置文件my.cnf里加[mysqld] slow_query_log 1 slow_query_log_file /var/log/mysql/slow.log long_query_time 0.5 log_queries_not_using_indexes 1 min_examined_row_limit 1000改完重启或SET GLOBAL动态生效。long_query_time0.5是抓 500ms 以上的min_examined_row_limit1000过滤掉扫描行数太少的噪音。采集一段时间后用pt-query-digest聚合pt-query-digest /var/log/mysql/slow.log slow_report.txt报告里按Query_time和Rows_examined排序挑出 Top 10 慢 SQL。接下来把这些 SQL 和表结构喂给模型。用 Python 调 TaoToken 的配置如下先建.envTAOTOKEN_BASE_URLhttps://taotoken.net/api TAOTOKEN_API_KEYsk-你的Key TAOTOKEN_MODELclaude-sonnet-4-5再写调用脚本analyze_sql.pyimport os import requests from dotenv import load_dotenv load_dotenv() BASE_URL os.getenv(TAOTOKEN_BASE_URL) API_KEY os.getenv(TAOTOKEN_API_KEY) MODEL os.getenv(TAOTOKEN_MODEL) def ask_model(prompt: str) - str: resp requests.post( f{BASE_URL}/v1/chat/completions, headers{ Authorization: fBearer {API_KEY}, Content-Type: application/json, }, json{ model: MODEL, messages: [ {role: system, content: 你是 MySQL 优化专家只输出可执行的索引 DDL 和改写后的 SQL不要解释。}, {role: user, content: prompt}, ], temperature: 0.2, }, timeout60, ) resp.raise_for_status() return resp.json()[choices][0][message][content] if __name__ __main__: slow_sql SELECT id, user_id, amount, status, created_at FROM t_order WHERE user_id 10086 AND status 1 ORDER BY created_at DESC LIMIT 20; ddl CREATE TABLE t_order ( id BIGINT PRIMARY KEY, user_id BIGINT, shop_id BIGINT, amount DECIMAL(10,2), status TINYINT, created_at DATETIME, KEY idx_user (user_id) ); prompt f表结构\n{ddl}\n\n慢SQL\n{slow_sql}\n\n给出索引建议和改写SQL。 print(ask_model(prompt))这段脚本的关键点temperature0.2让输出稳定system prompt 约束它只输出 DDL 和 SQL方便你直接复制执行。跑一次你会拿到类似ALTER TABLE t_order ADD INDEX idx_user_status_time (user_id, status, created_at)的建议以及把ORDER BY和过滤条件对齐的改写。分片配置这边如果用 ShardingSphereconfig-sharding.yaml片段rules: - !SHARDING tables: t_order: actualDataNodes: ds_${0..7}.t_order_${0..63} tableStrategy: standard: shardingColumn: user_id shardingAlgorithmName: order_inline databaseStrategy: standard: shardingColumn: user_id shardingAlgorithmName: db_inline shardingAlgorithms: order_inline: type: INLINE props: algorithm-expression: t_order_${user_id % 64} db_inline: type: INLINE props: algorithm-expression: ds_${user_id % 8}分片键选user_id的理由高频查询都带它能单分片路由缺点是运营按shop_id或时间范围查会广播到所有分片这类查询要么走离线数仓要么建异构索引表。别指望一个分片键解决所有查询。4. 验证请求与 QPS 前后对比配置写完必须验证否则你不知道优化有没有生效。验证分两层单条 SQL 的EXPLAIN对比和整体压测的 QPS 对比。先看EXPLAIN。优化前EXPLAIN SELECT id, user_id, amount, status, created_at FROM t_order WHERE user_id 10086 AND status 1 ORDER BY created_at DESC LIMIT 20;输出里typeref、keyidx_user、rows1200000、ExtraUsing where; Using filesort。加了联合索引(user_id, status, created_at)之后ALTER TABLE t_order ADD INDEX idx_user_status_time (user_id, status, created_at);再EXPLAINrows降到 20 左右Extra里的Using filesort消失因为ORDER BY created_at能直接走索引有序性。这一步的量化结果扫描行数从 120 万降到 20降了 5 个数量级。分片后的验证要确认路由正确。开 ShardingSphere 的 SQL 日志执行同一条查询日志里应该只出现ds_3.t_order_42这样的单分片而不是 64 个分片全扫。如果看到广播说明分片键没命中回去检查查询条件是否带了user_id。压测用sysbench或mysqlslap。这里给sysbench的自定义 Lua 脚本order_query.luafunction event() local uid math.random(1, 10000000) db_query(SELECT id, amount, status FROM t_order WHERE user_id .. uid .. AND status 1 ORDER BY created_at DESC LIMIT 20) end跑压测sysbench order_query.lua --mysql-host127.0.0.1 --mysql-port3306 \ --mysql-userroot --mysql-passwordxxx --mysql-dborder_db \ --threads64 --time120 --report-interval10 run优化前实测 QPS 约 380P99 延迟 420ms加索引加分片后 QPS 到 2100 左右P99 降到 35ms。这个对比才是你要写进验证报告的硬数据。注意压测要在业务低峰跑别把生产库打挂。模型辅助这一环也可以量化把优化前后的EXPLAIN输出都喂给模型让它判断索引是否被正确使用。调用方式复用第 3 节的脚本把 prompt 换成「对比这两份 EXPLAIN指出是否还有全表扫描风险」。如果模型返回「仍有 filesort 风险」说明你的索引列顺序可能不对比如把status放在了created_at后面。5. 本篇常见报错排查优化链路上最容易撞的几类报错逐个对照。第一类模型调用返回 401。报错长这样{error:{message:Invalid API key,type:invalid_request_error}}。原因通常是 Key 复制时带了空格或者.env里变量名写错。排查echo $TAOTOKEN_API_KEY确认值检查请求头是不是Authorization: Bearer sk-xxxBase URL 是不是https://taotoken.net/api而不是别的路径。如果用了 Claude Code 接入确认走的是https://taotoken.net/claude-code-anthropic对应的配置三件套 Base URL、Key、Model ID 一个都不能少。第二类local proxy failed或连接超时。这多半是脚本里 Base URL 写成了带 UTM 的官网地址或者网络出口有问题。正确做法是 API 调用只用https://taotoken.net/api不要拼 UTM 参数。检查requests的timeout设置60 秒够用太短会误报。第三类reading choices报错形如KeyError: choices。说明返回体结构和你预期不一致常见于模型 ID 写错导致返回了错误对象。打印完整resp.json()看结构确认model字段是文档里支持的 ID。如果返回里是error而不是choices按错误信息改。第四类OAuth 相关报错。如果你用 Claude Code 或 Codex 这类工具报OAuth token expired或auth.json读取失败检查~/.codex/auth.json或对应工具的凭证文件确认 Base URL 指向 TaoToken 的通道Key 填的是 API Key 而不是 OAuth token。Codex 的auth.json里字段名要对齐文档写错字段会直接鉴权失败。第五类MySQL 侧报错。ERROR 1071 (42000): Specified key was too long说明联合索引列太长比如varchar(255)的列加进索引超了限制。改用前缀索引KEY idx_name (col(20))或换更短的列。ERROR 1215: Cannot add foreign key constraint在分片表上很常见分片后跨库外键不可用改成应用层保证一致性。第六类分片后查询结果不对。比如ORDER BY created_at跨分片排序ShardingSphere 会在内存里归并数据量大时 OOM。排查看是否带了user_id让查询落到单分片如果必须跨分片改用「按时间分片 二次查询」或走离线表。6. 继续验证与工具入口优化不是一次性的索引会随查询模式漂移分片键也可能随业务变化失效。建议把第 3 节的模型调用脚本做成定时任务每周拉一次慢查询 Top 20让模型批量出建议人工审核后灰度上线。压测脚本也保留每次 DDL 变更后跑一轮对比。需要继续验证模型输出、对比不同模型的 SQL 改写质量可以用模型对话入口https://taotoken.net/model-chat?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content把慢 SQL 和表结构贴进去直接问。要管理 Key、看用量进控制台https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content要新建或轮换 Key用 API Keys 页面https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content。接入细节以文档https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content为准。长期跑批量 SQL 分析和 Agent 任务Coding Plan 入口https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content更合适。最后留一个实用技巧把每次优化的「慢 SQL、EXPLAIN 前后、QPS 前后」记成一张表时间久了你会发现哪些索引是真正被用到的哪些是白加的。索引不是越多越好写入放大和优化器选错索引都是代价。分片键一旦定了改的成本极高上线前一定用真实查询模式压测验证。
返回列表