zoukankan      html  css  js  c++  java
  • (六)MySQL如何优化--ORDER BY

    ---
    title: 不懂SQL优化?那你就OUT了(六)

    MySQL如何优化--ORDER BY

    date: 2018-12-08

    categories: 数据库优化
    ---



    在日常开发中,我们经常会使用 order by 子句对某些数据进行排序处理,那么在mysql中使用order by子句时,我们应该怎样优化order by 子句后的查询字段来提高查询效率和排序速度。

    在mysql中使用 order by 进行排序有两种方式:

    1. 扫描有序索引进行排序(推荐)

    2. 使用文件进行排序(using filesort:内存/磁盘文件排序获取结果 )

    在InnoDB存储引擎以B+树作为索引的底层实现,B+树的叶子节点存储着所有数据页而内部节点不存放数据信息,并且所有叶子节点形成一个(双向)链表。

    你可以简单的理解为:索引是一种特殊的文件,当我们建立索引时,mysql会使用双向链表的方式来事先给数据进行排序。

    例如:

    CREATE TABLE t_testOrderBy(

    userid INT PRIMARY KEY AUTO_INCREMENT, -- 用户编号

    username VARCHAR(25), -- 用户姓名

    userAge INT, -- 用户年龄

    usergender CHAR(3), -- 用户性别

    provice VARCHAR(25), -- 所在省份

    city VARCHAR(25), -- 所在城市

    address VARCHAR(200) -- 详细地址
    );

    测试数据:


    INSERT INTO t_testOrderBy VALUES(NULL,'张三',18,'男','四川省','成都市','xxxx路222号');
    INSERT INTO t_testOrderBy VALUES(NULL,'李四',20,'女','云南省','昆明市','xxx北路12号');
    INSERT INTO t_testOrderBy VALUES(NULL,'王五',24,'男','贵州省','遵义市','xxxxx路18号');
    INSERT INTO t_testOrderBy VALUES(NULL,'赵六',19,'女','四川省','绵阳市','xx路234号');
    INSERT INTO t_testOrderBy VALUES(NULL,'孙琦',28,'男','云南省','玉溪市','xxxx路324号');
    INSERT INTO t_testOrderBy VALUES(NULL,'王晓琪',21,'女','云南省','玉溪市','xxxx路123号');


    例如:

    图1:

    从图1可以看出:

    使用userid进行排序时,userid上有主键索引,mysql会直接遍历userid索引的叶子节点链表,不需要进行额外的排序操作,这就是用索引扫描来排序。

    使用 username 字段上没有任何索引,此时B+树结构不存在,mysql就只能先扫表筛选出符合条件的数据,再将筛选结果根据username排序。这个排序过程就是filesort。


    ### 使用有序索引排序时

    sql语句中,where子句和order by 子句都可以使用索引, where子句使用索引避免全表扫描,order by 子句使用索引尽量避开使用文件排序(filesort),以提高查询效率。

    虽然索引能提高查询效率,但在一条sql里,对于一张表的查询 一次只能使用一个索引(注:排除发生index merge的可能性),也就是说当where子句与order by 子句使用的索引不一致时,MySQL只能使用其中一个索引(B+树)。

    ####order by 可以使用索引

    1. 当select的字段包含在索引中时,能利用到索引排序功能,进行覆盖索引扫描.

    例如: 为表中的username添加索引。




    可以看出当 select 字段中包含了 userage(未建立索引)时,则不能使用索引。

    2.当有联合索引时,order by 子句使用索引必须遵循索引的最左前缀原则。

    例如: 为 省份,城市,详细地址建立联合索引





    当不遵循最左前缀原则时,则会使用filesort



    3.联合索引中的一部分做等值查询 ,另一部分作为排序字段。(当然还是要遵循最左前缀原则)




    ####order by 不使用索引排序

    1.select字段在多个索引中,无法使用索引排序。


    从上图中可以看出,username的一个独立的所以,二而provice是联合索引,当select字段中有多个索引列时,无法使用索引排序


    2.对不同的关键字使用ORDER BY:

    3.当有联合索引时,order by 子句使用索引 不 遵循索引的最左前缀原则,无法使用索引排序


    4. 升降序不一致,无法使用索引排序。




    5.order by 的字段使用函数

    6.返回数据量过大也会不使用索引。

    ## 使用文件进行排序(后面在介绍)

    对于不能利用索引避免排序的sql,数据库不得不自己实现排序功能以满足用户需求,此时sql的执行计划中会出现“Using filesort”,这里需要注意的是filesort并不意味着就是文件排序,其实也有可能是内存排序,这个主要由sort_buffer_size参数与结果集大小确定。


    如果排序不可避免,可以用下面的办法加速:

    1. 避免使用 “select * ” 。

    2. 增加sort_buffer_size变量的大小。

    3. 增加read_rnd_buffer_size变量的大小。

    4. 更改tmpdir指向具有大量空闲空间的专用文件系统。

    5. 使用合适的列大小存储具体的内容,比如对于city字段 varchar(25)比varchar(200)能获取更好的性能.


    ##order by 总结


  • 相关阅读:
    Adobe Flash Builder 4.5 Android Air 程序开发系列 之六 多点触控
    Adobe Flash Builder 4.5 Android Air 程序开发系列 之九 定位
    Adobe Flash Builder 4.5 Android Air 程序开发系列 之七 重力感应
    Adobe Flash Builder 4.5 Android Air 程序开发系列 之五 保存数据的几种方式
    Adobe Flash Builder 4.5 Android Air 程序开发系列 之八 照相机
    Adobe Flash Builder 4.5 Android Air 程序开发系列 之三 Application 配置详解
    Adobe Flash Builder 4.5 Android Air 程序开发系列 之四 打开与关闭应用程序是的保存数据
    ADOBE FLASH BUILDER 4.6 IOS 开发之部署与调试
    [译] 高性能JavaScript 1至5章总结
    页签及盒子的web标准实现
  • 原文地址:https://www.cnblogs.com/ysviewvicn/p/10288302.html
Copyright © 2011-2022 走看看