MySQL慢查询优化实战一例

发表于:2016-6-08 10:03

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:清水先生    来源:51Testing软件测试网采编

#
MySQL
分享:
  一、查看表结构
CREATE TABLE `happy_for_ni_labels` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name_chn` varchar(255) NOT NULL DEFAULT '0' COMMENT '标签的名字',
`status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '标签状态',
`xx_tag_id` int(11) NOT NULL DEFAULT '0' COMMENT '关联XxTag#ID',
`created_at` datetime NOT NULL,
`updated_at` datetime NOT NULL,
`xxxxx_tag_id` int(11) NOT NULL DEFAULT '0' COMMENT 'xxxxx_tags.id(新分类体系)',
PRIMARY KEY (`id`),
KEY `idx_name_chn_with_id` (`name_chn`,`id`),
KEY `idx_xx_tag_id_with_id` (`xx_tag_id`,`id`),
KEY `idx_ptag_id` (`xxxxx_tag_id`,`id`)
) ENGINE=InnoDB AUTO_INCREMENT=719 DEFAULT CHARSET=utf8 COMMENT='报名活动标签'
CREATE TABLE `happy_for_ni_label_links` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`happy_for_ni_id` int(11) NOT NULL DEFAULT '0' COMMENT '关联HappyForNi#ID',
`checked_happy_for_ni_id` int(11) NOT NULL DEFAULT '0' COMMENT '关联CheckedHappyForNi#ID',
`label_id` int(11) NOT NULL DEFAULT '0' COMMENT '关联HappyForNiLabel#ID',
`status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '关联状态(可用、删除)',
`created_at` datetime NOT NULL,
`updated_at` datetime NOT NULL,
PRIMARY KEY (`id`),
KEY `idx_label_id_with_id` (`label_id`,`id`),
KEY `idx_status_happy_for_ni_id_with_id` (`happy_for_ni_id`,`status`,`id`),
KEY `idx_status_checked_happy_for_ni_id_with_id` (`checked_happy_for_ni_id`,`status`,`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2048836 DEFAULT CHARSET=utf8 COMMENT='报名活动标签关联表'
  执行查询计划可知
explain SELECT `happy_for_ni_labels`.`id`
FROM `happy_for_ni_labels`
INNER JOIN `happy_for_ni_label_links`
ON `happy_for_ni_labels`.`id` = `happy_for_ni_label_links`.`label_id` WHERE `happy_for_ni_label_links`.`happy_for_ni_id` = 3369231
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: happy_for_ni_labels
type: index
possible_keys: PRIMARY
key: idx_xx_tag_id_with_id
key_len: 8
ref: NULL
rows: 461
Extra: Using index
*************************** 2. row ***************************
id: 1
select_type: SIMPLE
table: happy_for_ni_label_links
type: ref
possible_keys: idx_label_id_with_id
key: idx_label_id_with_id
key_len: 4
ref: my_local_test.happy_for_ni_labels.id
rows: 1872
Extra: Using WHERE
2 rows in set (0.00 sec)
ERROR:
No query specified
  本来想用到 idx_status_happy_for_ni_id_with_id 但是实际上只用到了 idx_label_id_with_id 这个索引,所以根据现有的资料。
  优化有两种方案
  去掉现有的索引,重新生成索引。
  重用现在的索引,修改查询语句。
  二、去掉现有的索引,重新生成索引。
  mysql> SELECT count(id), status
  -> FROM happy_for_ni_label_links
  -> GROUP BY status;
  ERROR 2006 (HY000): MySQL server has gone away
  No connection. Trying to reconnect...
  Connection id:    112463
  Current database: my_local_test
  +-----------+--------+
  | count(id) | status |
  +-----------+--------+
  |    980377 |      0 |
  +-----------+--------+
  1 row in set (2.27 sec)
  status 只有为 0 的值。这里其实是个败笔。创建这个表的作者(也就是我),当时考虑到由于业务需要,会查询各种不同状态下的数据量,故设计了这个status。但实际情况,该状态,只有一个为0的值,不需要看索引记录也知道,该列上的选择性太差。建议,不要将该列放在索引第一位。
21/212>
100家互联网大公司java笔试题汇总,填问卷领取~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2023
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号