Using filsort文档中的解释:

Mysql需要额外的一次传递,以找出如何按排序顺序检索行,通过根据联接类型浏览所有行并为所有匹配where子句的行保存排序关键字和行的指针来完成排序,然后关键字被排序,并按排序顺序检索行。额外的传递是指什么?

Mysql> show create table test_filesort\G;

*************************** 1. row ***************************

   Table: test_filesort

Create Table: CREATE TABLE `test_filesort` (

`a` int(11) DEFAULT NULL,

`b` int(11) DEFAULT NULL,

`c` int(11) DEFAULT NULL,

KEY `a_2` (`a`)

) ENGINE=MyISAM DEFAULT CHARSET=latin1

1 row in set (0.00 sec)

ERROR:

No query specified

Mysql> explain select * from test_filesort where a=1 order by b;

+----+-------------+---------------+------+---------------+------+---------+-------+------+-----------------------------+

| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |

+----+-------------+---------------+------+---------------+------+---------+-------+------+-----------------------------+

| 1 | SIMPLE | test_filesort | ref | a_2 | a_2 | 5 | const | 1 | Using where; Using filesort |

+----+-------------+---------------+------+---------------+------+---------+-------+------+-----------------------------+

1 row in set (0.00 sec)

Mysql> alter table test_filesort add index(a,b);

Query OK, 6 rows affected (0.04 sec)

Records: 6 Duplicates: 0 Warnings: 0

Mysql> explain select * from test_filesort where a=1 order by b;

+----+-------------+---------------+------+---------------+------+---------+-------+------+-------------+

| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |

+----+-------------+---------------+------+---------------+------+---------+-------+------+-------------+

| 1 | SIMPLE | test_filesort | ref | a_2,a | a | 5 | const | 1 | Using where |

+----+-------------+---------------+------+---------------+------+---------+-------+------+-------------+

1 row in set (0.00 sec)

额外传递指的是多做了一次排序,很少人会把所有需要排序的字段都放到索引中,出现Using filesort不一定就会有什么性能问题。当然,我是希望尽量在应用中实现order by排序,如果放在数据库这边实现,查询次数又非常大的话,尽量考虑把字段直接冗余到索引中去,避免Mysql自身的排序机制可能会引起的性能下降。

1.order by时可能会出现Using filesort。

2.order by b,如果b列不在索引中,不管b值是否相同,总会出现Using filesort。

3.并不是说所有的索引都可以避免Using filesort,hash索引是不按顺序来保存数据的。

1.如果order by 没有利用到索引,那么将会出现fileSort,如果sort_buffer不够大,fileSort过程则需要使用临时文件,fileSort优化,主要通过调整环境来达到,如下

2.设置参数,优化order by 时可能出现的file sort:

   将sort_buffer_size = 1M  read_rnd_buffer_size = 1M

   修改为sort_buffer_size = 16M read_rnd_buffer_size = 16M

避免order by 过程 进行fileSort排序过程临时文件的产生。从3秒->0.7秒左右

参考:MySQL Order By实现原理分析和Filesort优化

3. 优化Filesort

当无法避免排序操作时,又该如何来优化呢?很显然,应该尽可能让 MySQL 选择使用第二种单路算法来进行排序。这样可以减少大量的随机IO操作,很大幅度地提高排序工作的效率。

1. 加大 max_length_for_sort_data 参数的设置

在 MySQL 中,决定使用老式排序算法还是改进版排序算法是通过参数 max_length_for_ sort_data 来决定的。当所有返回字段的最大长度小于这个参数值时,MySQL 就会选择改进后的排序算法,反之,则选择老式的算法。所以,如果有充足的内存让MySQL 存放须要返回的非排序字段,就可以加大这个参数的值来让 MySQL 选择使用改进版的排序算法。

2. 去掉不必要的返回字段

当内存不是很充裕时,不能简单地通过强行加大上面的参数来强迫 MySQL 去使用改进版的排序算法,否则可能会造成 MySQL 不得不将数据分成很多段,然后进行排序,这样可能会得不偿失。此时就须要去掉不必要的返回字段,让返回结果长度适应 max_length_for_sort_data 参数的限制。

3. 增大 sort_buffer_size 参数设置

增大 sort_buffer_size 并不是为了让 MySQL选择改进版的排序算法,而是为了让MySQL尽量减少在排序过程中对须要排序的数据进行分段,因为分段会造成 MySQL 不得不使用临时表来进行交换排序。

注:

key:显示Mysql实际决定使用的索引

Using index:只从索引中检索数据,不回表

key_len:显示Mysql决定使用的键长度

rows:显示Mysql认为它执行查询时必须检查的行数

ref:使用哪个列或常数与key一起从表中选择行

possible_keys:指出Mysql可以使用哪个索引在该表中找到行

网上案例分析:

MySQL 数据库,MyISAM 类型的表 table_item,有 5、6 个字段,主键是 id。

user_id 和 item_id 两个字段都是单独的 INDEX 类型的索引。

问题是如何发现的?

在自己的开发环境下,打开一个简单的页面都要好长时间,不知道问题出在哪里,只发现硬盘灯闪个不停。

观察 Windows 的任务管理器,看到 mysqld-nt.exe 这个进程的 "I/O 读取字节" 高达十几 G!!!

再次测试,发现每次刷新页面,这个进程要读取几十 M 的数据。

奇了怪了,查看 SQL 语句,还有表结构,字段都建了索引了呀。
后来 EXPLAIN 了一下,看到结果是 Using where; Using filesort。

explain SELECT * FROM table_item WHERE user_id = 2 ORDER BY item_id LIMIT 0, 5

翻了 MySQL 手册,仔细看下 filesort 的说明,知道了 Using filesort 是一种速度很慢的外部排序。

不过我不理解为什么会使用 filesort 排序,WHERE 和 ORDER BY 用到的字段都是有索引的呀。

赶紧 Google之,得到的启示就是索引定义不当导致MySQL 没有用到索引。

需要了解MySQL 的特性:

1.一条 SQL 语句只能使用 1 个索引 (5.0-)[5.0+MYSQ会分析是否做index megre],MySQL 根据表的状态,选择一个它认为最好的索引用于优化查询【use index 指定索引,纠正MYSQL错误判断】

2.联合索引,只能按从左到右的顺序依次使用,包括了group order

3.从上边可以看到结合索引,也可以叫多列索引,形如 key ('B1','B2','B3' ,'B4')等的,排序的思路通常为,先按照B1来排序,B1相同,然后按照B2排序,以此类推,这样对于(B1),(B1,B2), (B1,B2,B3)的索引都是有效的,可是对于(B2,B3)这样的索引就无效了。

根据这个特性就可以解决问题:

user_id 和 item_id 是 2 个索引,我的语句中,MySQL 选择了 user_id,那么 item_id 的索引没有起到任何用处,所以,当我要排序的时候,由于user_id索引取得的记录数较多,内存中的排序 buffer 满了,只能 Using filesort 进行外部排序,因此每次查询要从磁盘读取几十 M 的数据,太慢了。

修改表结构,删除 user_id 和 item_id 的 INDEX 索引,建立一个名为 user_item 的联合 UNIQUE 索引,顺序是先 user_id 后 item_id,再 EXPLAIN,这回只有 Using where 了。

再刷新页面,观察任务管理器,mysqld-nt.exe 只读取了 2K 的数据,页面咔的一下就出来了……

using_where, Using temporary ,using_filesort 分享的更多相关文章

  1. iOS之ShareSDK实现分享、第三方登录等功能

    (1)官方下载ShareSDK iOS 2.8.8,地址:http://sharesdk.cn/ (2)根据实际情况,引入相关的库,参考官方文档. (3)在项目的AppDelegate中一般情况下有三 ...

  2. iOS开发---集成ShareSDK实现第三方登录、分享、关注等功能。

    (1)官方下载ShareSDK IOS 2.9.6,地址:http://sharesdk.mob.com/Download (2)根据实际情况,引入相关的库,参考官方文档. (3)在项目的AppDel ...

  3. IOS项目集成ShareSDK实现第三方登录、分享、关注等功能。

    (1)官方下载ShareSDK iOS 2.8.8,地址:http://sharesdk.cn/ (2)根据实际情况,引入相关的库,参考官方文档. (3)在项目的AppDelegate中一般情况下有三 ...

  4. IOS项目集成ShareSDK实现第三方登录、分享、关注等功能(备用)

    (1)官方下载ShareSDK iOS 2.8.8,地址:http://sharesdk.cn/ (2)根据实际情况,引入相关的库,参考官方文档. (3)在项目的AppDelegate中一般情况下有三 ...

  5. iOS开发之第三方分享QQ分享,史上最新最全第三方分享QQ方式实现

    本文章源码地址: https://github.com/zhonggaorong/QQLoginDemo 项目搭建参考:  (包含QQ登录源码下载 . QQ sdk集成) http://blog.cs ...

  6. 淘宝内部分享:怎么跳出MySQL的10个大坑

    编者按:淘宝自从2010开始规模使用MySQL,替换了之前商品.交易.用户等原基于IOE方案的核心数据库,目前已部署数千台规模.同时和Oracle, Percona, Mariadb等上游厂商有良好合 ...

  7. 每周分享之 二 http协议(2)

    本次分享http协议,共分为三部分,这是第二部分,主要讲解请求与响应的字段,以及状态码. 以http/1.1版本的一个完整的请求与响应作为例子 http请求信息由三部分组成 1.请求方法(GET/PO ...

  8. iOS ShareSDK 三方分享/登录使用

    原文 http://www.cnblogs.com/CoderAlex/p/4860352.html 一: 快速集成 1.前言 作为现在App里必不可少的用户分享需要,社交化分享显然是我们开发app里 ...

  9. 沉淀,再出发——在Ubuntu Kylin15.04中配置Hadoop单机/伪分布式系统经验分享

    在Ubuntu Kylin15.04中配置Hadoop单机/伪分布式系统经验分享 一.工作准备 首先,明确工作的重心,在Ubuntu Kylin15.04中配置Hadoop集群,这里我是用的双系统中的 ...

随机推荐

  1. sql server 2012中red gate的sql source control消失

    找到C:\ProgramData\Microsoft\SQL Server Management Studio\11.0\Addins路径,用notepad++打开RedGate.SIPFramewo ...

  2. hdoj--1281--棋盘游戏(最小点覆盖+枚举)

    棋盘游戏 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submi ...

  3. nyoj--79--导弹拦截(动态规划)

    拦截导弹 时间限制:3000 ms  |  内存限制:65535 KB 难度:3 描述 某国为了防御敌国的导弹袭击,发展中一种导弹拦截系统.但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任 ...

  4. 通过top 5等待事件查看sql语句

    设计的动态性能视图有:v$session_event,v$session,v$sqlarea,首先在v$session_event中可以找到event,然后通过其动态性能视图找到sid,可以在v$se ...

  5. kindoreditor上传图片

    <!doctype html><html> <head> <meta charset="utf-8" /> <title> ...

  6. SwiftUI 官方教程(一)

    完整中文教程及代码请查看 https://github.com/WillieWangWei/SwiftUI-Tutorials   创建和组合 View 此部分将指引你构建一个发现和分享您喜爱地方的 ...

  7. Oracle 11g RAC for LINUX rhel 6.X silent install(静默安装)

    一.前期规划 1.硬件环境 CPU: Intel(R) Xeon(R) CPU E7-4820 v4 @ 2.00GHz  8*10核 内存:512GB OCR:2147*5 MB DATA1:2TB ...

  8. 关于api接口文档RAP和swagger

    前言: 在之前的项目中用了将近一年的RAP,RAP是由阿里开源出来的,非常好用.github地址:https://github.com/thx/RAP. 当初在用此工具时,项目成员需要在接口文档在所改 ...

  9. SQL使用总结——集合操作函数

    Oracle中集合操作符专门用于合并多条select 语句的结果,包括:UNION, UNION ALL, INTERSECT, MINUS.当使用集合操作符时,必须确保不同查询的列个数和数据类型匹配 ...

  10. php 微信支付 回调通知不停的坑

    微信支付已完工,最后有点小问题就是微信的回调会重复9次 第一步: $return = "success"; echo $return; 不管用 第二步: $return = &qu ...