mysql临时表产生的执行效率问题改进(转)
- 问题:
近日,线上MySQL查出一个慢sql,每次都要查询1000ms以上,严重影响用户体验
今得空去诊断一番,记录如下:
sql原句:
- SELECT r.object_id AS cardId, count(1) AS attachs FROM hzresource_object r
- LEFT JOIN
- ( SELECT card_id FROM card_member WHERE user_id = #uid# and card_member.deleted=0
- UNION
- SELECT card_id FROM card_subscribed where user_id = #uid# and card_subscribed.deleted=0
- ) m ON r.object_id = m.card_id
- WHERE r.object_type = #objectType# AND r.deleted = 0
- GROUP BY r.object_id;
- 解决问题:
由于对数据库优化一知半解,完全无从下手,只能求助度娘和谷哥了,试验了各种方法,都不见效果
几番周折之后,最终把注意力集中到了临时表上,因为explain查看执行计划,可以看到Using temporary
MySQL在执行SQL查询时可能会用到临时表,一般情况下,用到临时表就意味着性能较低。
于是想办法修改sql语句,摒弃临时表,修改如下:
- SELECT r.object_id AS cardId, count(1) AS attachs FROM hzresource_object r
- WHERE r.object_type = #objectType# AND r.deleted = 0 and r.object_id in (
- SELECT card_id FROM card_member WHERE user_id = #uid# and card_member.deleted=0
- UNION
- SELECT card_id FROM card_subscribed where user_id = #uid# and card_subscribed.deleted=0
- )
- GROUP BY r.object_id;
即把语句给拆分成两个sql语,用in操作拼接
- 本机测试:
优化前执行时间1040ms,优化后执行时间:85ms,执行速度是原来的12倍多!赞
- PS:
常理我们都会排斥用in操作,用union替换,那为什么这里用in会更快呢?
带着问题,接着去网上找,原来:
sql执行会生成一个巨大的临时表,当内存放不下时,要全部copy 到磁盘,导致IO飙升,时间开销增大。
额外收获知识收藏如下:
- 临时表存储
MySQL临时表分为“内存临时表”和“磁盘临时表”,其中内存临时表使用MySQL的MEMORY存储引擎,磁盘临时表使用MySQL的MyISAM存储引擎;
一般情况下,MySQL会先创建内存临时表,但内存临时表超过配置指定的值后,MySQL会将内存临时表导出到磁盘临时表;
- 使用临时表的场景
1)ORDER BY子句和GROUP BY子句不同, 例如:ORDERY BY price GROUP BY name;
2)在JOIN查询中,ORDER BY或者GROUP BY使用了不是第一个表的列 例如:SELECT * from TableA, TableB ORDER BY TableA.price GROUP by TableB.name
3)ORDER BY中使用了DISTINCT关键字 ORDERY BY DISTINCT(price)
4)SELECT语句中指定了SQL_SMALL_RESULT关键字 SQL_SMALL_RESULT的意思就是告诉MySQL,结果会很小,请直接使用内存临时表,不需要使用索引排序 SQL_SMALL_RESULT必须和GROUP BY、DISTINCT或DISTINCTROW一起使用 一般情况下,我们没有必要使用这个选项,让MySQL服务器选择即可。
- 直接使用磁盘临时表的场景
1)表包含TEXT或者BLOB列;
2)GROUP BY 或者 DISTINCT 子句中包含长度大于512字节的列;
3)使用UNION或者UNION ALL时,SELECT子句中包含大于512字节的列;
- 表的设计原则
使用临时表一般都意味着性能比较低,特别是使用磁盘临时表,性能更慢,因此我们在实际应用中应该尽量避免临时表的使用。 常见的避免临时表的方法有:
1)创建索引:在ORDER BY或者GROUP BY的列上创建索引;
2)分拆很长的列:一般情况下,TEXT、BLOB,大于512字节的字符串,基本上都是为了显示信息,而不会用于查询条件, 因此表设计的时候,应该将这些列独立到另外一张表。
- SQL优化
如果表的设计已经确定,修改比较困难,那么也可以通过优化SQL语句来减少临时表的大小,以提升SQL执行效率。
常见的优化SQL语句方法如下:
1)拆分SQL语句
临时表主要是用于排序和分组,很多业务都是要求排序后再取出详细的分页数据,这种情况下可以将排序和取出详细数据拆分成不同的SQL,以降低排序或分组时临时表的大小,提升排序和分组的效率,我们的案例就是采用这种方法。
2)优化业务,去掉排序分组等操作
有时候业务其实并不需要排序或分组,仅仅是为了好看或者阅读方便而进行了排序,例如数据导出、数据查询等操作,这种情况下去掉排序和分组对业务也没有多大影响。
- 如何判断使用了临时表?
使用explain查看执行计划,Extra列看到Using temporary就意味着使用了临时表。
- 小结:
可见, 完全颠覆了对in操作符的认识,凡事儿都是要分情况讨论的
mysql临时表产生的执行效率问题改进(转)的更多相关文章
- mySQL数据库Sql语句执行效率检查--Explain命令
mysql性能的检查和调优方法 Explain命令在解决数据库性能上是第一推荐使用命令,大部分的性能问题可以通过此命令来简单的解决,Explain可以用来查看SQL语句的执行效 果,可以帮助选择更好的 ...
- MySQL查看SQL语句执行效率
Explain命令在解决数据库性能上是第一推荐使用命令,大部分的性能问题可以通过此命令来简单的解决,Explain可以用来查看 SQL 语句的执行效 果,可以帮助选择更好的索引和优化查询语句,写出更好 ...
- MySQL查看SQL语句执行效率(转)
Explain命令在解决数据库性能上是第一推荐使用命令,大部分的性能问题可以通过此命令来简单的解决,Explain可以用来查看 SQL 语句的执行效 果,可以帮助选择更好的索引和优化查询语句,写出更好 ...
- mysql 查看语句的执行效率
EXPLAIN 一.用途: 1.什么时候必须为表加入索引以得到一个使用索引找到记得的更快的select 2.知道优化器是否以一个最佳次序联结表. <官方的关于explain的文档在http:// ...
- mysql is not null 执行效率低
a表字段类型为int b表字段类型为varchar a left join b时如果查询条件是is not null,效率很快,is null 效率很低 后来两者改为同类型 int,效率很高
- mysql优化(三)–explain分析sql语句执行效率
mysql优化(三)–explain分析sql语句执行效率 mushu 发布于 11个月前 (06-04) 分类:Mysql 阅读(651) 评论(0) Explain命令在解决数据库性能上是第一推荐 ...
- Mysql explain分析sql语句执行效率
mysql优化–explain分析sql语句执行效率 Explain命令在解决数据库性能上是第一推荐使用命令,大部分的性能问题可以通过此命令来简单的解决,Explain可以用来查看SQL语句的执行效 ...
- Mysql 定位执行效率低的sql 语句
一.通过MySQL慢查询日志定位执行效率低的SQL语句. MySQL通过慢查询日志定位那些执行效率较低的SQL 语句,用--log-slow-queries[=file_name]选项启动时,mysq ...
- php中使用mysqli和pdo扩展,测试mysql数据库的执行效率。
<?php /** * 测试pdo和mysqli的执行效率 */ header("Content-type:text/html;charset=utf-8"); //通过pd ...
随机推荐
- Linux SWAP 交换分区大小与内存的关系
LinuxSWAP交换分区大小与内存的关系SWAP(交换分区)[Windows虚拟内存]我们机房中一台Linux服务器运行缓慢,系统服务出现间歇性停止响应,让我过去处理一下这一问题,登录到服务器之后, ...
- 三篇文章了解 TiDB 技术内幕——说存储
数据库.操作系统和编译器并称为三大系统,可以说是整个计算机软件的基石.其中数据库更靠近应用层,是很多业务的支撑.这一领域经过了几十年的发展,不断的有新的进展. 很多人用过数据库,但是很少有人实现过一个 ...
- WinForm窗体继承
在Windows应用程序中,从现有的窗体继承,查看子窗体的设计视图时,会出现错误: 服务容器中已存在服务 System.Windows.Forms.Design.IEventHandlerServic ...
- 解决jar包乱码 in 创新实训 智能自然语言交流系统
今天用eclipse的fat jar插件,打成jar包.之后再命令行运行...程序的功能是切分大的文件...结果是切分的很正确,但是里面的中文都变成了乱码. 最开始以为是在Eclipse中的编码设置有 ...
- PHP CURL POST提交
$_post_url = 'http://XXXXX/XXX'; $post = 'key=12&content_id='.$content_id.'&md5='.$storeStat ...
- Linux中的链接文件_软链接和硬链接
一.链接文件介绍 Linux操作系统中的“链接文件”分为硬链接(hard link)和软链接(symbolic link).两种链接的本质区别在于inode.以下是详细介绍: 硬链接:当系统要读取一个 ...
- 第三百五十八节,Python分布式爬虫打造搜索引擎Scrapy精讲—将bloomfilter(布隆过滤器)集成到scrapy-redis中
第三百五十八节,Python分布式爬虫打造搜索引擎Scrapy精讲—将bloomfilter(布隆过滤器)集成到scrapy-redis中,判断URL是否重复 布隆过滤器(Bloom Filter)详 ...
- e798. 显示JSlider的标记标签
This example demonstrates how to display labels (numerical values) at the major ticks (see e797 显示JS ...
- C#基础---------------C#正则表达式2
C#正则表达式语法规则详解 正则表达式基础知识 一个正则表达式就是由普通字符(例如字符 a 到 z)以及特殊字符(称为元字符)组成的文字模式. 字母文本指的是普通文本如"a ...
- Enigma Virtual Box:生成可执行文件。
Enigma Virtual Box Enigma Virtual Box[1] 是软件虚拟化工具,它可以将多个文件封装到应用程序主文件,从而制作成为单执行文件的绿色软件.它支持所有类型的文件格式, ...