博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
mysql索引无效且sending data耗时巨大原因分析
阅读量:6084 次
发布时间:2019-06-20

本文共 5875 字,大约阅读时间需要 19 分钟。

 一朋友最近新上线一个项目,本地测试环境跑得好好的,部署到线上却慢得像蜗牛一样。后来查询了一下发现一个sql执行了16秒,有些长的甚至80秒。本地运行都是毫秒级别的查询。下面记录一下困扰了两天的,其中一条sql的优化。

  表结构及现象描述:

CREATE TABLE `wp_goods` (  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,  `user_openid` varchar(255) NOT NULL DEFAULT '',  `description` longtext ,  `upset_price` decimal(10,2) DEFAULT NULL ,  `reference_price` decimal(10,2) DEFAULT NULL ,  `offer_unit` decimal(10,2) DEFAULT NULL ,  `end_time` int(11) DEFAULT NULL ,  `type` tinyint(4) DEFAULT NULL ,  `is_bail` tinyint(4) DEFAULT NULL ,  `is_express` tinyint(4) DEFAULT NULL ,  `is_return` tinyint(4) DEFAULT NULL ,  `createtime` int(11) DEFAULT NULL ,  `is_sell` tinyint(4) DEFAULT NULL ,  `is_draft` tinyint(1) NOT NULL DEFAULT '1' ,  `scan_count` int(11) NOT NULL ,  `title` varchar(255) NOT NULL ,  `is_trash` tinyint(1) NOT NULL DEFAULT '1' ,  `countdown` smallint(6) NOT NULL DEFAULT '0' ,  `bail_money` tinyint(4) NOT NULL DEFAULT '0' ,  `cat_id` tinyint(4) NOT NULL,  `sort` int(10) unsigned NOT NULL DEFAULT '1' ,  PRIMARY KEY (`id`),  KEY `cat_id` (`cat_id`),  KEY `index_id_user_openid` (`id`,`user_openid`) USING BTREE,  KEY `index_user_openid` (`user_openid`) USING BTREE,  KEY `index_id` (`id`) USING BTREE) ENGINE=MyISAM AUTO_INCREMENT=10094 DEFAULT CHARSET=utf8;CREATE TABLE `sys_users` (  `id` int(11) NOT NULL AUTO_INCREMENT,  `openid` varchar(50) DEFAULT NULL,  `nickname` varchar(20) DEFAULT NULL,  `sex` char(255) DEFAULT NULL,  `phone` varchar(11) DEFAULT NULL,  `country` varchar(10) DEFAULT NULL,  `province` varchar(10) DEFAULT NULL,  `city` varchar(10) DEFAULT NULL,  `headimgurl` varchar(200) DEFAULT NULL,  `createtime` varchar(20) DEFAULT NULL,  `is_subject` tinyint(4) NOT NULL DEFAULT '1' ,  `black` tinyint(4) NOT NULL DEFAULT '1' ,  `wd_sort` smallint(5) unsigned DEFAULT '1000' ,  `wp_sort` smallint(5) unsigned NOT NULL DEFAULT '1000' ,  PRIMARY KEY (`id`),  UNIQUE KEY `openid` (`openid`)) ENGINE=MyISAM AUTO_INCREMENT=14044 DEFAULT CHARSET=utf8;CREATE TABLE `jd_jianding` (  `id` int(11) NOT NULL AUTO_INCREMENT,  `expert_id` int(11) DEFAULT NULL ,  `gid` int(11) DEFAULT NULL ,  `goods_value` varchar(50) DEFAULT NULL ,  `result` varchar(500) DEFAULT NULL ,  `jdtime` int(11) DEFAULT NULL ,  `is_essence` tinyint(4) NOT NULL DEFAULT '0' ,  `istrue` tinyint(4) DEFAULT '0' ,  `wid` int(11) DEFAULT '0',  `scan_num` int(11) DEFAULT '0' ,  PRIMARY KEY (`id`),  UNIQUE KEY `uk_name` (`gid`),  KEY `index_wid` (`wid`) USING BTREE) ENGINE=MyISAM AUTO_INCREMENT=9142 DEFAULT CHARSET=utf8;

  表wp_goods数据量10094,sys_users数据量14044, jd_jianding数据量9142。

  执行sql:

SELECT   `g`.`id`,  `g`.`title`,  `g`.`upset_price`,  `u`.`nickname`,  `j`.`istrue` FROM  `wp_goods` `g`   LEFT JOIN `sys_users` `u`     ON g.user_openid = u.openid   LEFT JOIN `jd_jianding` `j`     ON g.id = j.wid ORDER BY `g`.`id` DESC LIMIT 6 ;

  耗时16秒,而本地数据库执行耗时0.02毫秒。

  原因分析:

  1、explain/desc 发现left join索引不起作用。

explain SELECT   `g`.`id`,  `g`.`title`,  `g`.`upset_price`,  `u`.`nickname`,  `j`.`istrue` FROM  `wp_goods` `g`   LEFT JOIN `sys_users` `u`     ON g.user_openid = u.openid   LEFT JOIN `jd_jianding` `j`     ON g.id = j.wid ORDER BY `g`.`id` DESC LIMIT 6 ;

  分析结果:

id    select_type    table    partitions    type    possible_keys    key    key_len    ref    rows    filtered    Extra1    SIMPLE    g    \N    ALL    \N    \N    \N    \N    10093    100.00    Using temporary; Using filesort1    SIMPLE    u    \N    ref    openid    openid    153    mydb.g.user_openid    10    100.00    Using where1    SIMPLE    j    \N    ALL    index_wid    \N    \N    \N    7975    100.00    Using where; Using join buffer (Block Nested Loop)

  索引无效,Using join buffer (Block Nested Loop)相当于遍历表查询。

  2、profile分析了下,发现几乎所有耗时都在sending data且缓存sending cached result to clien没开启。

  show variables like '%cache%';

  query_cache_type为off,在配置文件/etc/my.cf中添加“query_cache_type = 1”配置项并重启。

  执行后耗时10s,如果将order by去掉后耗时3秒。即使是耗时3秒也是无法接受的。

  通过profile分析下具体耗时

SHOW VARIABLES LIKE '%profil%'SET profiling = 1;SELECT   `g`.`id`,  `g`.`title`,  `g`.`upset_price`,  `u`.`nickname`,  `j`.`istrue` FROM  `wp_goods` `g`   LEFT JOIN `sys_users` `u`     ON g.user_openid = u.openid   LEFT JOIN `jd_jianding` `j`     ON g.id = j.wid ORDER BY `g`.`id` DESC LIMIT 6 ;show profile for query 1;

  

  发现几乎所有耗时都在sending data部分。

  3、查看jd_jianding表索引,show index from jd_jianding发现cardinality的值为1。

  

Table    Non_unique    Key_name    Seq_in_index    Column_name    Collation    Cardinality    Sub_part    Packed    Null    Index_type    Comment    Index_commentjd_jianding    0    PRIMARY    1    id    A    7975    \N    \N        BTREE        jd_jianding    0    uk_name    1    gid    A    \N    \N    \N    YES    BTREE        jd_jianding    1    index_wid    1    wid    A    1    \N    \N    YES    BTREE

  4、优化表jd_jianding,analyze table jd_jianding,再次执行仍然如此。

  然而mysql的文档时这么说的。The higher the cardinality, the greater the chance that MySQL uses the index when doing joins. 

  An estimate of the number of unique values in the index. This is updated by running ANALYZE TABLE or myisamchk -a. Cardinality is counted based on statistics stored as integers, so the value is not necessarily exact even for small tables. The higher the cardinality, the greater the chance that MySQL uses the index when doing

  大意如下:

1)、它代表的是索引中唯一值的数目的估计值。如果是myisam引擎,这个值是一个准确的值。如果是innodb引擎,这个值是一个估算的值,每次执行show index 时,可能会不一样   2)、创建Index时(primary key除外),MyISAM的表Cardinality的值为null,InnoDB的表Cardinality的值大概为行数;   3)、值的大小会影响到索引的选择   4)、创建Index时,MyISAM的表Cardinality的值为null,InnoDB的表Cardinality的值大概为行数。   5)、可以通过Analyze table来更新一张表或者mysqlcheck -Aa来进行更新整个数据库   6)、可以通过 show index 查看其值

  5、查看表jd_jianding字段wid的值全为默认值0,于是将其中一条记录的wid字段值update为非0;再次analyze table jd_jianding。

  再次执行,效果杠杠的,耗时只有0.02毫秒。困扰两天的问题终于得到了解决。

  6、把步骤4修改的字段值还原回来。

 

  后记,原因大致如下:

1、mysql没有开启查询缓存。2、新添加字段默认值都一样,导致索引不可用。

本文转自秋楓博客园博客,原文链接:http://www.cnblogs.com/rwxwsblog/p/5684213.html,如需转载请自行联系原作者

你可能感兴趣的文章
使用grep、awk统计查询日志
查看>>
Spring 5 core 中的 @NonNull 是个什么鬼?!
查看>>
vsftpd系列--2--匿名访问控制
查看>>
Excel工作表保护破解方法
查看>>
实现geo相关
查看>>
SSM项目搭建三(终)
查看>>
vmware esxi基础篇之模版与克隆
查看>>
拥抱 Gradle: 下一代自动化工具
查看>>
CyclicBarrier让多线程齐步走
查看>>
tomcat与web程序结构与Http协议与HttpUrlConnection
查看>>
PHPStorm下调试使用CURL抓取数据中文乱码的一种可能
查看>>
解决hadoop namenode -format / hdfs namenode -format 找不到java的文件目录
查看>>
springMVC 几种页面跳转方式
查看>>
Python的集合类型详解17
查看>>
HBase配置优化
查看>>
英特网级别的服务设计及部署
查看>>
动态路由
查看>>
mssql dba問題與答案
查看>>
悦悦走好
查看>>
分享一些 Kafka 消费数据的小经验
查看>>