Mysql表关联字段未建索引导致查询慢,优化后查询效率显著提升
发表于:2026-11-01 作者:千家信息网编辑
千家信息网最后更新 2026年11月01日,今天收到用户反馈前端页面打开很慢。数据库服务器负载也告警了。登录服务器查询Mysql占用CPU过高,很直接打开show full process 跟慢查询发现很多以下sql都是在10S以上# User
千家信息网最后更新 2026年11月01日Mysql表关联字段未建索引导致查询慢,优化后查询效率显著提升今天收到用户反馈前端页面打开很慢。数据库服务器负载也告警了。
登录服务器查询Mysql占用CPU过高,很直接打开show full process 跟慢查询发现很多以下sql都是在10S以上
# User@Host: gyw[gwy] @ [x.x.x.x] Id: 19513
# Query_time: 11.326904 Lock_time: 0.000327 Rows_sent: 69 Rows_examined: 1417696
SET timestamp=1504507662;
SELECT odet.seller AS sellerId,
odet.agreementprice_id AS agreementpriceId,
odet.customer_id AS customerId,
(SELECT realname
FROM sys_user suser
WHERE suser.id = odet.seller)
AS sellerName,
odet.pkgticket_id AS pkgId,
odet.pkgticket_price AS pkgPrice,
DATE_FORMAT(odet.sell_time, '%Y-%m-%d') AS sellTime,
sum(oct.tourist_number-IFNULL(ort.tourist_remain,0)) as totalPeople,
sum((oct.tourist_number-IFNULL(ort.tourist_remain,0))*odet.pkgticket_price) as totalMoney,
(SELECT name
FROM scenic_pkgticket spkg
WHERE spkg.id = odet.pkgticket_id)
AS pkgticketName
FROM order_detail odet,order_checkticket oct
LEFT JOIN order_refundticket ort
on oct.id = ort.id
WHERE odet.id=oct.order_detail_id
and odet.scenic_id = 215
and odet.sell_time >= '2017-09-04 00:00:00'
and odet.sell_time <= '2017-09-04 23:59:59'
GROUP BY sellerId, sellTime, pkgId, pkgPrice
WITH ROLLUP;
手动查看一下执行计划发现,使用Using temporary; Using filesort使用到了临时表,这样效率是最差的
explain SELECT odet.seller AS sellerId,
-> odet.agreementprice_id AS agreementpriceId,
-> odet.customer_id AS customerId,
-> (SELECT realname FROM sys_user suser WHERE suser.id = odet.seller) AS sellerName,
-> odet.pkgticket_id AS pkgId,
-> odet.pkgticket_price AS pkgPrice,
-> DATE_FORMAT(odet.sell_time, '%Y-%m-%d') AS sellTime,
-> sum(oct.tourist_number - IFNULL(ort.tourist_remain, 0)) as totalPeople,
-> sum((oct.tourist_number - IFNULL(ort.tourist_remain, 0)) *
-> odet.pkgticket_price) as totalMoney,
-> (SELECT name
-> FROM scenic_pkgticket spkg
-> WHERE spkg.id = odet.pkgticket_id) AS pkgticketName
-> FROM order_detail odet, order_checkticket oct
-> LEFT JOIN order_refundticket ort
-> on oct.id = ort.id
-> WHERE odet.id = oct.order_detail_id
-> and odet.scenic_id = 215
-> and odet.sell_time >= '2017-09-04 00:00:00'
-> and odet.sell_time <= '2017-09-04 23:59:59'
-> GROUP BY sellerId, sellTime, pkgId, pkgPrice WITH ROLLUP;
+----+--------------------+-------+--------+---------------+---------+---------+----------------------------+--------+---------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+--------------------+-------+--------+---------------+---------+---------+----------------------------+--------+---------------------------------+
| 1 | PRIMARY | oct | ALL | NULL | NULL | NULL | NULL | 414589 | Using temporary; Using filesort |
| 1 | PRIMARY | ort | eq_ref | PRIMARY | PRIMARY | 8 | sd_ets.oct.id | 1 | NULL |
| 1 | PRIMARY | odet | eq_ref | PRIMARY | PRIMARY | 8 | sd_ets.oct.order_detail_id | 1 | Using where |
| 3 | DEPENDENT SUBQUERY | spkg | eq_ref | PRIMARY | PRIMARY | 8 | func | 1 | NULL |
| 2 | DEPENDENT SUBQUERY | suser | eq_ref | PRIMARY | PRIMARY | 8 | func | 1 | NULL |
+----+--------------------+-------+--------+---------------+---------+---------+----------------------------+--------+---------------------------------+
尝试在在order_detail 上加一个复合索引(scenic_id,sell_time),但是依然如此未走索引,仔细检查发现order_checkticket order_detail_id未建索引。加上索引后执行计划如下
+----+--------------------+-------+--------+-------------------------+-----------------+---------+----------------+------+--------------------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+--------------------+-------+--------+-------------------------+-----------------+---------+----------------+------+--------------------------------------------------------+
| 1 | PRIMARY | odet | range | PRIMARY,idx_od_si_stime | idx_od_si_stime | 14 | NULL | 183 | Using index condition; Using temporary; Using filesort |
| 1 | PRIMARY | oct | ref | idx_oct_odi | idx_oct_odi | 8 | sd_ets.odet.id | 1 | NULL |
| 1 | PRIMARY | ort | eq_ref | PRIMARY | PRIMARY | 8 | sd_ets.oct.id | 1 | NULL |
| 3 | DEPENDENT SUBQUERY | spkg | eq_ref | PRIMARY | PRIMARY | 8 | func | 1 | NULL |
| 2 | DEPENDENT SUBQUERY | suser | eq_ref | PRIMARY | PRIMARY | 8 | func | 1 | NULL |
+----+--------------------+-------+--------+-------------------------+-----------------+---------+----------------+------+--------------------------------------------------------+
5 rows in set (0.00 sec)
我们看key已经走了索引使用idx_od_si_stime
查询速度只要0.01毫秒。提升速度上千倍
登录服务器查询Mysql占用CPU过高,很直接打开show full process 跟慢查询发现很多以下sql都是在10S以上
# User@Host: gyw[gwy] @ [x.x.x.x] Id: 19513
# Query_time: 11.326904 Lock_time: 0.000327 Rows_sent: 69 Rows_examined: 1417696
SET timestamp=1504507662;
SELECT odet.seller AS sellerId,
odet.agreementprice_id AS agreementpriceId,
odet.customer_id AS customerId,
(SELECT realname
FROM sys_user suser
WHERE suser.id = odet.seller)
AS sellerName,
odet.pkgticket_id AS pkgId,
odet.pkgticket_price AS pkgPrice,
DATE_FORMAT(odet.sell_time, '%Y-%m-%d') AS sellTime,
sum(oct.tourist_number-IFNULL(ort.tourist_remain,0)) as totalPeople,
sum((oct.tourist_number-IFNULL(ort.tourist_remain,0))*odet.pkgticket_price) as totalMoney,
(SELECT name
FROM scenic_pkgticket spkg
WHERE spkg.id = odet.pkgticket_id)
AS pkgticketName
FROM order_detail odet,order_checkticket oct
LEFT JOIN order_refundticket ort
on oct.id = ort.id
WHERE odet.id=oct.order_detail_id
and odet.scenic_id = 215
and odet.sell_time >= '2017-09-04 00:00:00'
and odet.sell_time <= '2017-09-04 23:59:59'
GROUP BY sellerId, sellTime, pkgId, pkgPrice
WITH ROLLUP;
手动查看一下执行计划发现,使用Using temporary; Using filesort使用到了临时表,这样效率是最差的
explain SELECT odet.seller AS sellerId,
-> odet.agreementprice_id AS agreementpriceId,
-> odet.customer_id AS customerId,
-> (SELECT realname FROM sys_user suser WHERE suser.id = odet.seller) AS sellerName,
-> odet.pkgticket_id AS pkgId,
-> odet.pkgticket_price AS pkgPrice,
-> DATE_FORMAT(odet.sell_time, '%Y-%m-%d') AS sellTime,
-> sum(oct.tourist_number - IFNULL(ort.tourist_remain, 0)) as totalPeople,
-> sum((oct.tourist_number - IFNULL(ort.tourist_remain, 0)) *
-> odet.pkgticket_price) as totalMoney,
-> (SELECT name
-> FROM scenic_pkgticket spkg
-> WHERE spkg.id = odet.pkgticket_id) AS pkgticketName
-> FROM order_detail odet, order_checkticket oct
-> LEFT JOIN order_refundticket ort
-> on oct.id = ort.id
-> WHERE odet.id = oct.order_detail_id
-> and odet.scenic_id = 215
-> and odet.sell_time >= '2017-09-04 00:00:00'
-> and odet.sell_time <= '2017-09-04 23:59:59'
-> GROUP BY sellerId, sellTime, pkgId, pkgPrice WITH ROLLUP;
+----+--------------------+-------+--------+---------------+---------+---------+----------------------------+--------+---------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+--------------------+-------+--------+---------------+---------+---------+----------------------------+--------+---------------------------------+
| 1 | PRIMARY | oct | ALL | NULL | NULL | NULL | NULL | 414589 | Using temporary; Using filesort |
| 1 | PRIMARY | ort | eq_ref | PRIMARY | PRIMARY | 8 | sd_ets.oct.id | 1 | NULL |
| 1 | PRIMARY | odet | eq_ref | PRIMARY | PRIMARY | 8 | sd_ets.oct.order_detail_id | 1 | Using where |
| 3 | DEPENDENT SUBQUERY | spkg | eq_ref | PRIMARY | PRIMARY | 8 | func | 1 | NULL |
| 2 | DEPENDENT SUBQUERY | suser | eq_ref | PRIMARY | PRIMARY | 8 | func | 1 | NULL |
+----+--------------------+-------+--------+---------------+---------+---------+----------------------------+--------+---------------------------------+
尝试在在order_detail 上加一个复合索引(scenic_id,sell_time),但是依然如此未走索引,仔细检查发现order_checkticket order_detail_id未建索引。加上索引后执行计划如下
+----+--------------------+-------+--------+-------------------------+-----------------+---------+----------------+------+--------------------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+--------------------+-------+--------+-------------------------+-----------------+---------+----------------+------+--------------------------------------------------------+
| 1 | PRIMARY | odet | range | PRIMARY,idx_od_si_stime | idx_od_si_stime | 14 | NULL | 183 | Using index condition; Using temporary; Using filesort |
| 1 | PRIMARY | oct | ref | idx_oct_odi | idx_oct_odi | 8 | sd_ets.odet.id | 1 | NULL |
| 1 | PRIMARY | ort | eq_ref | PRIMARY | PRIMARY | 8 | sd_ets.oct.id | 1 | NULL |
| 3 | DEPENDENT SUBQUERY | spkg | eq_ref | PRIMARY | PRIMARY | 8 | func | 1 | NULL |
| 2 | DEPENDENT SUBQUERY | suser | eq_ref | PRIMARY | PRIMARY | 8 | func | 1 | NULL |
+----+--------------------+-------+--------+-------------------------+-----------------+---------+----------------+------+--------------------------------------------------------+
5 rows in set (0.00 sec)
我们看key已经走了索引使用idx_od_si_stime
查询速度只要0.01毫秒。提升速度上千倍
索引
查询
服务器
速度
服务
效率
最差
上千
前端
手动
数据
数据库
是在
用户
用户反馈
页面
x.x.x.x
尝试
检查
登录
数据库的安全要保护哪些东西
数据库安全各自的含义是什么
生产安全数据库录入
数据库的安全性及管理
数据库安全策略包含哪些
海淀数据库安全审计系统
建立农村房屋安全信息数据库
易用的数据库客户端支持安全管理
连接数据库失败ssl安全错误
数据库的锁怎样保障安全
小米移动互联网科技园
互联网科技工作委员会主任
科技互联网企业
互联网科技官网
科技互联网项目
科技企业和互联网企业
高科技与互联网
期待互联网科技
卓越科技(互联网 )
壹账通互联网科技
猫创互联网科技
富国互联网科技创新基金
成都互联网科技公司100强
互联网为啥属于高科技
科技互联网大厂
米聚互联网科技南京有限公司排面
北京市互联网新科技
上海创道互联网络科技有限公司
福建互联网展示科技馆设计
广东猫王互联网科技有限公司电话
北京互联网科技公司
嘟嘟瓜互联网科技
凡科互联网科技
亿账通互联网科技
融贸通互联网科技
深圳市运趣互联网科技有限公司
科技大学互联网
上海京穆互联网科技有限公司
互联网科技职业技能培训学校
承德科技产业互联网平台