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

  表结构及现象描述:

  1. CREATE TABLE `wp_goods` (
  2. `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  3. `user_openid` varchar(255) NOT NULL DEFAULT '',
  4. `description` longtext ,
  5. `upset_price` decimal(10,2) DEFAULT NULL ,
  6. `reference_price` decimal(10,2) DEFAULT NULL ,
  7. `offer_unit` decimal(10,2) DEFAULT NULL ,
  8. `end_time` int(11) DEFAULT NULL ,
  9. `type` tinyint(4) DEFAULT NULL ,
  10. `is_bail` tinyint(4) DEFAULT NULL ,
  11. `is_express` tinyint(4) DEFAULT NULL ,
  12. `is_return` tinyint(4) DEFAULT NULL ,
  13. `createtime` int(11) DEFAULT NULL ,
  14. `is_sell` tinyint(4) DEFAULT NULL ,
  15. `is_draft` tinyint(1) NOT NULL DEFAULT '' ,
  16. `scan_count` int(11) NOT NULL ,
  17. `title` varchar(255) NOT NULL ,
  18. `is_trash` tinyint(1) NOT NULL DEFAULT '' ,
  19. `countdown` smallint(6) NOT NULL DEFAULT '' ,
  20. `bail_money` tinyint(4) NOT NULL DEFAULT '' ,
  21. `cat_id` tinyint(4) NOT NULL,
  22. `sort` int(10) unsigned NOT NULL DEFAULT '' ,
  23. PRIMARY KEY (`id`),
  24. KEY `cat_id` (`cat_id`),
  25. KEY `index_id_user_openid` (`id`,`user_openid`) USING BTREE,
  26. KEY `index_user_openid` (`user_openid`) USING BTREE,
  27. KEY `index_id` (`id`) USING BTREE
  28. ) ENGINE=MyISAM AUTO_INCREMENT=10094 DEFAULT CHARSET=utf8;
  29.  
  30. CREATE TABLE `sys_users` (
  31. `id` int(11) NOT NULL AUTO_INCREMENT,
  32. `openid` varchar(50) DEFAULT NULL,
  33. `nickname` varchar(20) DEFAULT NULL,
  34. `sex` char(255) DEFAULT NULL,
  35. `phone` varchar(11) DEFAULT NULL,
  36. `country` varchar(10) DEFAULT NULL,
  37. `province` varchar(10) DEFAULT NULL,
  38. `city` varchar(10) DEFAULT NULL,
  39. `headimgurl` varchar(200) DEFAULT NULL,
  40. `createtime` varchar(20) DEFAULT NULL,
  41. `is_subject` tinyint(4) NOT NULL DEFAULT '' ,
  42. `black` tinyint(4) NOT NULL DEFAULT '' ,
  43. `wd_sort` smallint(5) unsigned DEFAULT '' ,
  44. `wp_sort` smallint(5) unsigned NOT NULL DEFAULT '' ,
  45. PRIMARY KEY (`id`),
  46. UNIQUE KEY `openid` (`openid`)
  47. ) ENGINE=MyISAM AUTO_INCREMENT=14044 DEFAULT CHARSET=utf8;
  48.  
  49. CREATE TABLE `jd_jianding` (
  50. `id` int(11) NOT NULL AUTO_INCREMENT,
  51. `expert_id` int(11) DEFAULT NULL ,
  52. `gid` int(11) DEFAULT NULL ,
  53. `goods_value` varchar(50) DEFAULT NULL ,
  54. `result` varchar(500) DEFAULT NULL ,
  55. `jdtime` int(11) DEFAULT NULL ,
  56. `is_essence` tinyint(4) NOT NULL DEFAULT '' ,
  57. `istrue` tinyint(4) DEFAULT '' ,
  58. `wid` int(11) DEFAULT '',
  59. `scan_num` int(11) DEFAULT '' ,
  60. PRIMARY KEY (`id`),
  61. UNIQUE KEY `uk_name` (`gid`),
  62. KEY `index_wid` (`wid`) USING BTREE
  63. ) ENGINE=MyISAM AUTO_INCREMENT=9142 DEFAULT CHARSET=utf8;

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

  执行sql:

  1. SELECT
  2. `g`.`id`,
  3. `g`.`title`,
  4. `g`.`upset_price`,
  5. `u`.`nickname`,
  6. `j`.`istrue`
  7. FROM
  8. `wp_goods` `g`
  9. LEFT JOIN `sys_users` `u`
  10. ON g.user_openid = u.openid
  11. LEFT JOIN `jd_jianding` `j`
  12. ON g.id = j.wid
  13. ORDER BY `g`.`id` DESC
  14. LIMIT 6 ;

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

  原因分析:

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

  1. explain SELECT
  2. `g`.`id`,
  3. `g`.`title`,
  4. `g`.`upset_price`,
  5. `u`.`nickname`,
  6. `j`.`istrue`
  7. FROM
  8. `wp_goods` `g`
  9. LEFT JOIN `sys_users` `u`
  10. ON g.user_openid = u.openid
  11. LEFT JOIN `jd_jianding` `j`
  12. ON g.id = j.wid
  13. ORDER BY `g`.`id` DESC
  14. LIMIT 6 ;

  分析结果:

  1. id select_type table partitions type possible_keys key key_len ref rows filtered Extra
  2. 1 SIMPLE g \N ALL \N \N \N \N 10093 100.00 Using temporary; Using filesort
  3. 1 SIMPLE u \N ref openid openid 153 mydb.g.user_openid 10 100.00 Using where
  4. 1 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分析下具体耗时

  1. SHOW VARIABLES LIKE '%profil%'
  2. SET profiling = 1;
  3.  
  4. SELECT
  5. `g`.`id`,
  6. `g`.`title`,
  7. `g`.`upset_price`,
  8. `u`.`nickname`,
  9. `j`.`istrue`
  10. FROM
  11. `wp_goods` `g`
  12. LEFT JOIN `sys_users` `u`
  13. ON g.user_openid = u.openid
  14. LEFT JOIN `jd_jianding` `j`
  15. ON g.id = j.wid
  16. ORDER BY `g`.`id` DESC
  17. LIMIT 6 ;
  18.  
  19. show profile for query 1;

  

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

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

  

  1. Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
  2. jd_jianding 0 PRIMARY 1 id A 7975 \N \N BTREE
  3. jd_jianding 0 uk_name 1 gid A \N \N \N YES BTREE
  4. 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. 1)、它代表的是索引中唯一值的数目的估计值。如果是myisam引擎,这个值是一个准确的值。如果是innodb引擎,这个值是一个估算的值,每次执行show index 时,可能会不一样
  2. 2)、创建Index时(primary key除外),MyISAM的表Cardinality的值为nullInnoDB的表Cardinality的值大概为行数;
  3. 3)、值的大小会影响到索引的选择
  4. 4)、创建Index时,MyISAM的表Cardinality的值为nullInnoDB的表Cardinality的值大概为行数。
  5. 5)、可以通过Analyze table来更新一张表或者mysqlcheck -Aa来进行更新整个数据库
  6. 6)、可以通过 show index 查看其值

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

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

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

  后记,原因大致如下:

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

mysql索引无效且sending data耗时巨大原因分析的更多相关文章

  1. mysql查询语句出现sending data耗时解决

    在执行一个简单的sql查询,表中数据量为14万 sql语句为:SELECT id,titile,published_at from spider_36kr_record where is_analyz ...

  2. MYSQL 索引无效和索引有效的详细介绍

    1.WHERE字句的查询条件里有不等于号(WHERE column!=...),MYSQL将无法使用索引 2.类似地,如果WHERE字句的查询条件里使用了函数(如:WHERE DAY(column)= ...

  3. MySQL在删除表时I/O错误原因分析

    欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 本文由腾讯数据库技术 发表于云+社区专栏 问题现象 最近使用sysbench测试MySQL,由于测试时间较长,写了一个脚本按prepare- ...

  4. mysql索引创建和使用细节

    最近困扰自己很久的膝盖积液手术终于做完,在家养伤,逛技术博客看到easyswoole开发组成员仙士可博客有关mysql索引方面的知识,自己打算重温下. 正常业务起步数据表数据量较少,不用考虑使用索引, ...

  5. 如何构建高性能MySQL索引

    本文的重点在于如何构建一个高性能的MySQL索引,从中你可以学到如何分析一个索引是不是好索引,以及如何构建一个好的索引. 索引误区 多列索引 一个索引的常见误区是为每一列创建一个索引,如下面创建的索引 ...

  6. MySQL Sending data导致查询很慢的问题详细分析【转载】

    转自http://blog.csdn.net/yunhua_lee/article/details/8573621 [问题现象] 使用sphinx支持倒排索引,但sphinx从mysql查询源数据的时 ...

  7. mysql查询sending data占用大量时间的问题处理

    问题描述:某条sql语句在测试环境执行只需要1秒不到,到了生产环境执行需要8秒以上 在phpmyadmin里面执行性能分析,发现sending data占用了差不多90%以上的时间 查询一下“Send ...

  8. 实战:MySQL Sending data导致查询很慢的问题详细分析(转)

    这两天帮忙定位一个MySQL查询很慢的问题,定位过程综合各种方法.理论.工具,很有代表性,分享给大家作为新年礼物:) [问题现象] 使用sphinx支持倒排索引,但sphinx从mysql查询源数据的 ...

  9. 实战:MySQL Sending data导致查询很慢的问题详细分析(转)

    出处:http://blog.csdn.net/yunhua_lee/article/details/8573621 这两天帮忙定位一个MySQL查询很慢的问题,定位过程综合各种方法.理论.工具,很有 ...

随机推荐

  1. Orchard源码分析(4.4):Orchard.Caching.CacheModule类

    概述 CacheModule也是一个Autofac模块.   一.CacheModule类 CacheModule将DefaultCacheManager注册为ICacheManager:       ...

  2. android-解决EditText的inputType为Password时, 字体不一致的问题

    今天做项目的时候,发现当edittext 的InputType为password时,它的字体和原来不一样: 网上找了一下,给出了解决办法: 第一: 去掉xml文件中的password配置,在代码中编写 ...

  3. tar命令的详细解释

    tar命令的详细解释 标签: linuxfileoutputbashinputshell 2010-05-04 12:11 235881人阅读 评论(12) 收藏 举报  分类: linux/unix ...

  4. some experience duing wrting myweb in php

    书写风格:一切以 最高效, 最简单为 标准!! 不必管格式的规范了! 在html中, 的属性是用双引号, 在php, tp中, 没有特殊情况, 都是用单引号. vim 下how to format c ...

  5. jquery判断checkbox是否选中及改变checkbox状态

    转自:http://blog.csdn.net/limingchuan123456789/article/details/11499665 jquery判断checked的三种方法:.attr('ch ...

  6. Eclipse中使用tomcat 8服务器初级教程

    Eclipse中使用tomcat容器时,经常遇到的问题是启动不成功,输入localhost:8080报404,本文就是教大家破解这个问题.(不过这是很初级的问题了,大牛勿喷) 步骤 1 Window- ...

  7. SQL pivot 基本用法 行列转换 数据透视

    SQL通过pivot进行行列转换 数据透视 可直接在sql server 运行 传统操作 和 pivot create table XKCl (name nchar(10) not null, 学科 ...

  8. PHP读取excel文档

    PHP读取excel文档 项目需要读取Excel的内容,从百度搜索了下,主要有两个选择,第一个是PHPExcelReader,另外一个是PHPExcel.   PHPExcelReader比较轻量级, ...

  9. html5开发制作,漂亮html5模板欣赏,H5网站建设

    html5是什么? HTML5 是下一代的 HTML(超文本标记语言,网页的组成部分),HTML5是web开发世界的一次重大的改变,能适配pc.手机等各终端,跨平台性能极强,移动互联网是未来的趋势,h ...

  10. win7下搭建web服务器

    简介 微软为了操作系统的安全,默认把web.ftp等服务默认关闭了,重新打开也非常简单. step 1 打开控制面板: step 2: step 3: step 4: 单击确定之后等个几分钟,web服 ...