• 索引查询MySQL前缀索引导致的慢查询


    首先声明,我是一个菜鸟。一下文章中出现技术误导情况盖不负责

        前端时间跟一个DB相干的项目,alanc反馈有一个查询,应用索引比不应用索引慢很多倍,有点毁三不雅。所以跟进了一下,用explain,看了看2个查询不同的结果。

        不必索引的查询的时候结果如下,实际查询中速度比较块。

        mysql> explain select * from rosterusers limit 10000,3 ;

        +----+-------------+-------------+------+---------------+------+---------+------+---------+-------+
    | id | select_type | table       | type | possible_keys | key  | key_len | ref  | rows    | Extra |
    +----+-------------+-------------+------+---------------+------+---------+------+---------+-------+
    |  1 | SIMPLE      | rosterusers | ALL  | NULL          | NULL | NULL    | NULL | 2010066 |       |
    +----+-------------+-------------+------+---------------+------+---------+------+---------+-------+

        而应用索引order by的查询结果如下,速度反而慢的惊人。

        mysql> explain select * from rosterusers order by username limit 10000,3 ;

        +----+-------------+-------------+------+---------------+------+---------+------+---------+----------------+
    | id | select_type | table       | type | possible_keys | key  | key_len | ref  | rows    | Extra          |
    +----+-------------+-------------+------+---------------+------+---------+------+---------+----------------+
    |  1 | SIMPLE      | rosterusers | ALL  | NULL          | NULL | NULL    | NULL | 2010087 | Using filesort |
    +----+-------------+-------------+------+---------------+------+---------+------+---------+----------------+

        区别在于,应用索引查询的Extra变成了,Using filesort。居然用了应用外部文件进行排序。这个当然慢了。

        但数据表上在username,的确是有索引的。怎么会反而要Using filesort?

        每日一道理
    爱心是一片照射在冬日的阳光,使贫病交迫的人感到人间的温暖;爱心是一泓出现在沙漠里的泉水,使濒临绝境的人重新看到生活的希望;爱心是一首飘荡在夜空的歌谣,使孤苦无依的人获得心灵的慰藉。

        看了一下数据表定义。是一个开源聊天服务器ejabberd的一张表。初看以为主键i_rosteru_user_jid是username,和jid的结合索引,那么应用order by username时应该是可以应用到索引才对呀?

        CREATE TABLE `rosterusers` (

        `username` varchar(250) NOT NULL,

        `jid` varchar(250) NOT NULL,

        UNIQUE KEY `i_rosteru_user_jid` (`username`(75),`jid`(75)),

        KEY `i_rosteru_jid` (`jid`)

        ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

        仔细检查突然发明其主键定义,不是定义的完整的主键名称,而跟了一个75的长度描述,稍稍一愣,原来用的是前缀索引,而不是整个字段都是索引。(我的记忆里头InnoDB还不支持这玩意,估计是4.0后什么版本参加的),前缀索引就是将数据字段中前面N个字节作为索引的一种方法。。

        发明了这个问题后,我们开始疑惑慢查询和这个索引有关,前缀索引的主要用途在于偶然字段进程,而MySQL支持的很多索引长度是有制约的。

        首先不带order by 的limit 这种查询,本质可能还是和主键相干的,因为MySQL 的INNODB的操纵实际都是依靠主键的(即使你没有建立,系统也会有一个默许的),而limit这种查询,应用主键是可以加快速度,(explain返回的rows 应该是一个参考值),虽然我没有看见什么文档明白的说明过这个问题,但从不带order by 的limit 查询的返回结果基本可以证明这点。

        但当我们应用order by username的时候,由于希望应用的是username的排序,而不是username(75)的排序,但实际索引是前缀索引,不是完整字段的索引。所以反而致使了order by的时候完整没法利用索引了。(我在SQL语句里头增长强制应用索引i_rosteru_user_jid也不起作用)。而其实应用中,表中的字段username 连75个都用不到,何况定义的250的长度。完整是自己折腾致使的费事。由于这是其他产品的表格,我们没法更改,临时只能先将就用不不带排序的查询讲究。

        总结:

        

    • 前缀索引,并不是一个万能药,他的确可以帮助我们对一个写过长的字段上建立索引。但也会致使排序(order by ,group by)查询上都是没法应用前缀索引的。
    • 任何时候,对于DB Schema定义,合理的规划自己的字段长度,字段类型都是首要的事件。

        【本文作者是雁渡寒潭,本着自在的精神,你可以在无红利的情况完整转载此文档,转载时请附上BLOG链接:http://www.cnblogs.com/fullsail/ 或者http://blog.csdn.net/fullsail,否则每字一元,每图一百不讲价。对Baidu文库,360doc加价一倍】

    文章结束给大家分享下程序员的一些笑话语录: IBM和波音777
      波音777是有史以来第一架完全在电脑虚拟现实中设计制造的飞机,所用的设备完全由IBM公司所提供。试飞前,波音公司的总裁非常热情的邀请IBM的技术主管去参加试飞,可那位主管却说道:“啊,非常荣幸,可惜那天是我妻子的生日,So..”..
      波音公司的总载一听就生气了:“胆小鬼,我还没告诉你试飞的日期呢!”

  • 相关阅读:
    oracle外连接 (+)
    Struts 2的架构和运行流程
    struts2.3.15.1 中jsp:include与jsp:forward的用法
    tomcat6.0添加ssi(*.shtml)配置
    DWZ 刷新 dialog
    java将多个连续的空格转化成一个空格
    IE下不支持option的onclick事件
    struts2中的常量
    java.imageIo给图片添加水印
    java集合的互转
  • 原文地址:https://www.cnblogs.com/jiangu66/p/3087206.html
Copyright © 2020-2023  润新知