MySQL三表JOIN查询添加serial空值条件后长时间无响应如何解决
问题定位步骤
- 先执行
EXPLAIN分析慢查询的执行计划,将你的查询语句前加上EXPLAIN后运行,检查输出结果里的type、key、rows字段,确认是否出现全表扫描、关联顺序异常、未命中索引的情况。 - 单独测试过滤条件的执行速度,运行
SELECT * FROM excel_terminal WHERE serial IS NULL OR serial = '';,如果该语句本身执行就很慢,基本可以确定是excel_terminal.serial字段没有索引导致的全表扫描。 - 检查关联字段的索引覆盖情况,确认三张表的关联字段
enduser.ncode、excel_merchant.reciver_ncode、excel_merchant.psp_recipt_code、excel_terminal.psp_recipt_code是否都建立了索引。 - 统计符合条件的数据占比,如果
excel_terminal表中serial为空/空字符串的记录占总数据量的20%以上,即使有索引数据库优化器也可能选择全表扫描,属于正常情况。
问题解决方法
- 优先添加联合索引,给
excel_terminal表创建联合索引idx_psp_serial(psp_recipt_code, serial),该索引可以同时覆盖关联条件和过滤条件,不需要回表查询就能完成数据筛选,大幅提升执行效率。 - 改写查询逻辑减少关联数据量,先过滤
excel_terminal的符合条件的记录再做关联,避免全表关联后再过滤,改写示例:
SELECT enduser.ncode, excel_merchant.psp_recipt_code, t.trminal_num, t.serial, t.shop_name, t.terminal_stat FROM enduser INNER JOIN excel_merchant on excel_merchant.reciver_ncode=enduser.ncode INNER JOIN ( SELECT * FROM excel_terminal WHERE serial IS NULL OR serial = '' ) t on excel_merchant.psp_recipt_code = t.psp_recipt_code
- 更新表统计信息,如果执行计划显示索引存在但未命中,运行
ANALYZE TABLE enduser,excel_merchant,excel_terminal;更新表的统计信息,修正优化器的执行计划选择。 - 排查web端超时限制,如果你是在phpmyadmin中执行查询,可先通过服务器本地的mysql命令行执行该语句,确认是查询本身慢还是phpmyadmin的执行超时配置过低导致无返回,确认为超时的话调整php.ini中的
max_execution_time参数即可。 - 确认关联逻辑是否正确:当前你使用的是
INNER JOIN excel_terminal,只有三张表都匹配的记录才会返回,如果你的业务需求是查询即使没有对应终端记录的用户/商户,需要将INNER JOIN改为LEFT JOIN,否则即使查询执行完也可能返回空结果。
内容的提问来源于stack exchange,提问作者hooman
相关产品推荐
相关产品推荐

