You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

同执行计划MySQL查询服务器与本地性能差异排查求助

MySQL查询性能环境差异排查与问题解答

问题描述

一条SELECT查询在服务器执行耗时15秒,本地环境仅需0.297秒,两者的EXPLAIN执行计划完全一致。现咨询两个问题:

  1. 需要检查哪些服务器参数以定位性能差异?
  2. EXPLAIN结果的表执行顺序是否会影响查询性能?

相关表结构

CREATE TABLE `Exam_Registration` ( 
    `examregnid` int(3) NOT NULL AUTO_INCREMENT, 
    `accountid` bigint(20) unsigned NOT NULL DEFAULT '0', 
    `examid` int(10) NOT NULL DEFAULT '0', 
    `examtype` int(1) NOT NULL DEFAULT '1' COMMENT '1-Regular,2-Supply,3-Betterment,4 -Notional', 
    `studentid` bigint(20) unsigned NOT NULL, 
    `colid` int(3) NOT NULL, 
    `courseid` int(3) NOT NULL, 
    `exrgstatus` int(1) NOT NULL COMMENT '1-Entry level,2-Apr by DEO,4-apr by Principal', 
    `internal_mark_status` int(1) NOT NULL COMMENT '1-Entry ,2-apr by DEO,3->apr by Principal', 
    `csid` int(6) NOT NULL, 
    `prjid` int(3) NOT NULL, 
    `examregn_supply` int(6) DEFAULT NULL, 
    `jr_appr_status` int(6) unsigned NOT NULL DEFAULT '0' COMMENT '1-Apr by JR', 
    `examreg_type` varchar(1) DEFAULT NULL COMMENT 'T - Provisonal Registration,P-Permanent Registration', 
    PRIMARY KEY (`examregnid`), 
    KEY `Index_2` (`accountid`,`examregnid`,`examid`,`colid`,`csid`,`prjid`) USING BTREE, 
    KEY `Index_3` (`accountid`), 
    KEY `Index_4` (`examregnid`), 
    KEY `Index_5` (`examid`), 
    KEY `Index_6` (`colid`) USING BTREE, 
    KEY `Index_7` (`csid`) USING BTREE, 
    KEY `Index_8` (`exrgstatus`) USING BTREE
) ENGINE=MyISAM AUTO_INCREMENT=1623337 DEFAULT CHARSET=latin1; 

CREATE TABLE `student_exam_external` ( 
    `stud_exm_ext_id` int(11) NOT NULL AUTO_INCREMENT, 
    `examid` int(11) NOT NULL, 
    `examregnid` int(11) NOT NULL, 
    `stud_paper_id` int(6) unsigned NOT NULL COMMENT '1 for internal only, 2 for external only, 3 for internal and external', 
    `accountid` bigint(20) unsigned NOT NULL COMMENT '1 for internal only, 2 for external only, 3 for internal and external', 
    `subid` int(6) NOT NULL, 
    `prent_abscent` char(2) NOT NULL DEFAULT 'P' COMMENT 'P for present, A for abscent', 
    `falsenumber` varchar(100) DEFAULT NULL, 
    `generated_falsenumber` varchar(100) DEFAULT NULL, 
    `falsenumber_mapped_user` int(10) unsigned DEFAULT NULL, 
    `falsenumber_mapped_date` datetime DEFAULT NULL, 
    `falsenumber_map_status` int(2) unsigned DEFAULT '1' COMMENT '0-not verified; 1 verified by ACO; 2 Verification failed; 3 duplicate entry; 4 infected barcode', 
    `theory_ext_weighted_grade_point` int(10) DEFAULT NULL, 
    `theory_ext_grade_point` decimal(10,2) DEFAULT NULL, 
    `theory_ext_grade` char(2) DEFAULT NULL, 
    `theory_ext_grade_entred_user` int(10) DEFAULT NULL, 
    `theory_ext_grade_entred_date` datetime DEFAULT NULL, 
    `theory_ext_grade_status` int(2) DEFAULT NULL, 
    `grade_verification` int(1) DEFAULT NULL COMMENT 'NULL- not verified, 1-ACO Verified, 2-CO Verified', 
    `additional_code` varchar(100) DEFAULT NULL, 
    `current_false_number` varchar(100) NOT NULL, 
    PRIMARY KEY (`stud_exm_ext_id`), 
    KEY `Index_5` (`examid`) USING BTREE, 
    KEY `Index_6` (`subid`) USING BTREE, 
    KEY `Index_7` (`examregnid`) USING BTREE, 
    KEY `Index_8` (`accountid`) USING BTREE, 
    KEY `Index_9` (`falsenumber`) USING BTREE, 
    KEY `Index_10` (`stud_paper_id`) USING BTREE, 
    KEY `Index_11` (`falsenumber_map_status`) USING BTREE, 
    KEY `Index_12` (`stud_exm_ext_id`) USING BTREE, 
    KEY `Index_13` (`stud_exm_ext_id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=5464239 DEFAULT CHARSET=latin1;

CREATE TABLE `Qpcode_Master` ( 
    `qpcode` int(11) NOT NULL DEFAULT '0', 
    `examid` int(6) NOT NULL DEFAULT '0', 
    `subid` int(6) NOT NULL DEFAULT '0', 
    `semid` int(3) NOT NULL DEFAULT '0', 
    `generated_date` datetime NOT NULL, 
    `verification_status` int(1) NOT NULL, 
    `approve_date` datetime NOT NULL, 
    `qpid` int(6) unsigned NOT NULL AUTO_INCREMENT, 
    `ug_qpcode` int(11) unsigned DEFAULT NULL, 
    PRIMARY KEY (`qpid`), 
    UNIQUE KEY `Index_5` (`qpcode`,`examid`,`subid`), 
    KEY `Index_6` (`examid`) USING BTREE, 
    KEY `Index_7` (`qpcode`) USING BTREE, 
    KEY `Index_8` (`subid`) USING BTREE, 
    KEY `Index_9` (`semid`)
) ENGINE=InnoDB AUTO_INCREMENT=171008480 DEFAULT CHARSET=latin1 DELAY_KEY_WRITE=1 ROW_FORMAT=DYNAMIC;

CREATE TABLE `camp_falseno_examiner_map` ( 
    `cmpexm_id` int(6) unsigned NOT NULL AUTO_INCREMENT, 
    `camp_id` int(6) unsigned NOT NULL, 
    `examid` int(6) DEFAULT NULL, 
    `qpcode` int(10) unsigned NOT NULL DEFAULT '0', 
    `st_range` int(20) unsigned NOT NULL DEFAULT '0', 
    `en_range` int(20) unsigned NOT NULL DEFAULT '0', 
    `chief_code` varchar(20) NOT NULL, 
    `additional_code` varchar(20) NOT NULL, 
    `entered_by` int(11) unsigned NOT NULL, 
    `entered_datetime` datetime NOT NULL, 
    PRIMARY KEY (`cmpexm_id`), 
    KEY `Index_2` (`examid`) USING BTREE, 
    KEY `Index_3` (`qpcode`) USING BTREE, 
    KEY `Index_4` (`st_range`) USING BTREE, 
    KEY `Index_5` (`en_range`) USING BTREE, 
    KEY `Index_6` (`camp_id`) USING BTREE, 
    KEY `Index_7` (`chief_code`) USING BTREE, 
    KEY `Index_8` (`additional_code`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=227704 DEFAULT CHARSET=latin1 ROW_FORMAT=FIXED;

CREATE TABLE `User_Details` ( 
    `user_tbl_id` int(50) unsigned NOT NULL AUTO_INCREMENT, 
    `User_Id` varchar(50) NOT NULL DEFAULT '', 
    `User_Type` char(8) NOT NULL, 
    `User_Name` varchar(50) NOT NULL, 
    `Password` varchar(100) NOT NULL, 
    `Password_old` varchar(100) NOT NULL, 
    `Status` char(1) NOT NULL, 
    `Camp` varchar(4) NOT NULL, 
    `college_id` int(11) DEFAULT NULL, 
    `prjid` int(1) unsigned NOT NULL, 
    `colid` int(3) unsigned NOT NULL, 
    `pwdstatus` int(1) unsigned NOT NULL DEFAULT '0' COMMENT '0-pwd not changed 1 -pwd changed', 
    `email` varchar(50) DEFAULT NULL, 
    `emailstatus` int(1) unsigned NOT NULL DEFAULT '0' COMMENT '0-email not updated 1 -email updated', 
    PRIMARY KEY (`User_Id`,`user_tbl_id`) USING BTREE, 
    UNIQUE KEY `Index_4` (`user_tbl_id`,`User_Id`) USING BTREE, 
    KEY `Index_3` (`user_tbl_id`) USING BTREE, 
    KEY `Index_5` (`User_Type`) USING BTREE, 
    KEY `Index_6` (`Status`) USING BTREE, 
    KEY `Index_7` (`User_Id`) USING BTREE, 
    KEY `Index_8` (`prjid`) USING BTREE, 
    KEY `Index_9` (`colid`) USING BTREE
) ENGINE=MyISAM AUTO_INCREMENT=104180 DEFAULT CHARSET=latin1;

查询语句

SELECT  distinct
        SE.stud_exm_ext_id,SE.falsenumber,            
        concat(UD.User_Name, ' - ',UD.User_Id)additional,
        UD.User_Id,
SE.theory_ext_weighted_grade_point,
        SE.theory_ext_grade_point,
SE.theory_ext_grade,
        SE.grade_verification, SE.additional_code
    FROM  Exam_Registration E
    INNER JOIN  student_exam_external SE
            ON SE.examid=E.examid
      and  SE.examregnid=E.examregnid
      and  SE.accountid=E.accountid
      and  SE.examid=47
    inner join  Qpcode_Master QM  ON QM.examid=E.examid
      and  QM.examid=E.examid
      AND  QM.subid=SE.subid
      and  QM.examid=47
      and  QM.qpcode=21101986
    inner join  camp_falseno_examiner_map CFE
              ON CFE.qpcode=QM.qpcode
      AND  CFE.examid=SE.examid
      AND  CFE.examid=QM.examid
      and  CFE.examid=E.examid
      and  CFE.examid=47
      and  CFE.qpcode=21101986
      and  CFE.st_range<=SE.falsenumber
      and  CFE.en_range>=SE.falsenumber
    inner join  User_Details UD -- use index(Index_7,PRIMARY)
            ON UD.User_Id=CFE.additional_code
      and  UD.User_Id=SE.additional_code
      and  UD.prjid=2
    where  QM.qpcode=21101986
      and  SE.examid=47
      and  SE.falsenumber>=314465
      and  SE.falsenumber<=314566
      and  SE.theory_ext_weighted_grade_point is not null
    order by  SE.falsenumber;

问题解答

1. 需要检查的服务器参数及系统指标

缓存相关参数

  • innodb_buffer_pool_size:InnoDB核心缓存,服务器该值过小会导致频繁磁盘读,本地环境数据量小可能缓存命中率更高。建议设置为服务器可用内存的50%-70%。
  • key_buffer_size:MyISAM索引缓存,你的Exam_Registration和User_Details是MyISAM表,若服务器该值不足,索引会频繁刷盘。
  • query_cache_size:仅针对MySQL 5.6及更早版本,若开启需检查缓存命中率,新版本已废弃该功能。

查询执行相关参数

  • sort_buffer_size:查询用到ORDER BY SE.falsenumber,若该值过小会触发磁盘排序,服务器压力大时可能出现性能瓶颈。
  • join_buffer_size:多表连接缓冲区,不足会导致临时表生成,拖慢连接速度。
  • optimizer_switch:确认服务器和本地的优化器开关完全一致,比如derived_merge、index_merge等关键选项。

系统与IO指标

  • CPU、内存使用率:用top、vmstat查看是否有其他进程抢占资源,导致MySQL无法分配足够资源。
  • 磁盘IO性能:用iostat查看磁盘读写延迟,服务器可能是机械盘或存在IO队列积压,本地则可能用SSD或负载低。
  • 网络延迟:若服务器是远程连接,需检查带宽和延迟,但50倍性能差大概率不是网络因素。

其他参数

  • max_connections、thread_cache_size:连接数过高会导致线程创建销毁开销大,检查是否有线程竞争。
  • innodb_flush_log_at_trx_commit、sync_binlog:严格的日志刷盘策略会增加IO开销,影响读查询性能。

2. EXPLAIN结果顺序对性能的影响

EXPLAIN的输出顺序(通过id列和表排列顺序)代表MySQL执行表的顺序,但如果两台环境的EXPLAIN所有字段完全一致(包括type、key、rows、Extra等),则执行计划逻辑相同,不会直接导致性能差异。

需注意:

  • 即使执行顺序相同,服务器的缓存命中率、磁盘IO速度、系统负载等环境因素,会导致实际执行时间差异巨大。
  • 仔细核对EXPLAIN的Extra字段,比如是否有Using temporary、Using filesort,以及rows列的预估行数是否一致。若有差异,可能是服务器表统计信息过时,需执行ANALYZE TABLE更新。

额外优化建议

  1. 清理查询冗余条件:多处重复的SE.examid=47、QM.qpcode=21101986可合并到一处,减少解析开销。
  2. 优化索引:
    • 给student_exam_external创建联合索引:(examid, falsenumber, theory_ext_weighted_grade_point, examregnid, accountid, subid, additional_code),覆盖查询所需字段,避免回表。
    • 给camp_falseno_examiner_map创建联合索引:(examid, qpcode, st_range, en_range, additional_code),加速范围匹配和连接。
  3. 替换MyISAM为InnoDB:MyISAM不支持事务、行级锁,并发场景性能差,建议将Exam_Registration和User_Details改为InnoDB引擎。

内容的提问来源于stack exchange,提问作者Lkbhai Lr

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 09:25:41