分析MySQL中优化distinct的技巧

 更新时间:2015年05月08日 09:41:15   作者:罗龙九  
这篇文章主要介绍了分析MySQL中优化distinct的技巧,主要是通过减少本地扫描的次数来进行优化的方法,需要的朋友可以参考下

有这样的一个需求:select count(distinct nick) from user_access_xx_xx;

这条sql用于统计用户访问的uv,由于单表的数据量在10G以上,即使在user_access_xx_xx上加上nick的索引,

通过查看执行计划,也为全索引扫描,sql在执行的时候,会对整个服务器带来抖动;

root@db 09:00:12>select count(distinct nick) from user_access;

+———————-+

| count(distinct nick) |

+———————-+

|        806934 |

+———————-+

1 row in set (52.78 sec)

执行一次sql需要花费52.78s,已经非常的慢了

现在需要换一种思路来解决该问题:

我们知道索引的值是按照索引字段升序的,比如我们对(nick,other_column)两个字段做了索引,那么在索引中的则是按照nick,other_column的升序排列:

我们现在的sql:select count(distinct nick) from user_access;则是直接从nick1开始一条条扫描下来,直到扫描到最后一个nick_n,

那么中间过程会扫描很多重复的nick,如果我们能够跳过中间重复的nick,则性能会优化非常多(在oracle中,这种扫描技术为loose index scan,但在5.1的版本中,mysql中还不能直接支持这种优化技术):

20155893909060.jpg (532×255)

所以需要通过改写sql来达到伪loose index scan:

root@db 09:41:30>select count(*) from ( select distinct(nick) from user_access)t ;

| count(*) |

+———-+

|  806934 |

1 row in set (5.81 sec)

Sql中先选出不同的nick,最后在外面套一层,就可以得到nick的distinct值总和;

最重要的是在子查询中:select distinct(nick) 实现了上图中的伪loose index scan,优化器在这个时候的执行计划为Using index for group-by ,

需要注意的是mysql把distinct优化为group by,它首先利用索引来分组,然后扫描索引,对需要的nick只扫描一次;

两个sql的执行计划分别为:

优化写法:

root@db 09:41:10>explain select distinct(nick) from user_access-> ;

+—-+————-+——————————+——-+—————+————-| id | select_type | table            | type | possible_keys | key               | key_len | ref | rows  | Extra          |

+—-+————-+——————————+——-+—————+————-

| 1 | SIMPLE   | user_access | range | NULL     | ind_user_access_nick | 67   | NULL | 2124695 | Using index for group-by |

+—-+————-+——————————+——-+—————+————-

原始写法:

root@db 09:42:55>explain select count(distinct nick) from user_access;

+—-+————-+——————————+——-+—————+————-

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

+—-+————-+——————————+——-+—————+————-

| 1 | SIMPLE   | user_access | index | NULL     | ind_user_access | 177   | NULL | 19546123 | Using index |

相关文章

  • Mysql8.0轻松实现主从复制

    Mysql8.0轻松实现主从复制

    这篇文章主要介绍了Mysql8.0轻松实现主从复制方法的相关资料,需要的朋友可以参考下
    2022-11-11
  • MySQL常见的存储引擎和区别说明

    MySQL常见的存储引擎和区别说明

    MySQL支持多种存储引擎,如InnoDB、MyISAM、MEMORY、Archive、CSV和Blackhole,每种引擎有其特点和适用场景,选择存储引擎时需根据业务需求考虑事务、性能、存储成本等因素
    2025-03-03
  • mysql8.0.21下载安装详细教程

    mysql8.0.21下载安装详细教程

    这篇文章主要介绍了mysql8.0.21下载安装详细教程,本文通过图文并茂的形式给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-08-08
  • 正确使用MySQL update语句

    正确使用MySQL update语句

    今天我们主要向大家讲述的是MySQL update 语句的实际用法,以及在实际操作中哪些相关的操作步骤是值得我们大家注意的。
    2015-08-08
  • 修改Mysql索引长度限制解决767 byte限制问题

    修改Mysql索引长度限制解决767 byte限制问题

    这篇文章主要介绍了修改Mysql索引长度限制解决767 byte限制问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-03-03
  • 浅谈mysql 自定义函数

    浅谈mysql 自定义函数

    本文主要是分析了一下在工作中写的一个mysql的自定义函数,很简单,仅仅是希望能对大家理解mysql自定义函数有所帮助。
    2014-09-09
  • 深入解读Mysql查询性能的优化

    深入解读Mysql查询性能的优化

    这篇文章主要介绍了深入解读Mysql查询性能的优化,如果想要优化查询,就需要优化其子任务,要么你就消除其中的一些子任务,要么就减少子任务的执行次数,要么就让子任务运行的更快,需要的朋友可以参考下
    2023-07-07
  • IDEA的database插件无法连接mysql的解决办法(08001错误)

    IDEA的database插件无法连接mysql的解决办法(08001错误)

    用navicat链接数据库正常,mysql控制台操作正常,但是用IDEA的数据库插件链接一直报 08001 错误,本文就给大家介绍一下IDEA的database插件无法连接mysql报08001错误的解决办法,需要的朋友可以参考下
    2024-07-07
  • MySQL修改密码方法汇总

    MySQL修改密码方法汇总

    本文中小编给大家汇总介绍了MySQL修改密码的方法,分为MySQL5.7版本之前以及MySQL5.7版本之后的修改方法,有需要的小伙伴可以参考下
    2018-08-08
  • navicat连接Mysql数据库报2013错误解决办法

    navicat连接Mysql数据库报2013错误解决办法

    这篇文章主要介绍了navicat连接Mysql数据库报2013错误的解决办法,首先检查MySQL是否安装成功,然后修改配置文件,添加或注释掉特定行,最后连接进入MySQL服务并执行授权命令,需要的朋友可以参考下
    2025-02-02

最新评论