MySQL调大sort_buffer_size,并发量一大,查询排序为啥又会变慢

本文探讨了MySQL在面对大量数据排序时,如何通过优先级队列排序算法提高性能,以及如何通过调整sort_buffer_size参数。同时,文章深入解析了MySQL内存分配器ptmalloc的工作原理,包括分配区、chunk、bins等概念,分析了并发场景下内存分配的性能问题。为了解决这些问题,文章介绍了tcmalloc内存分配器,详细阐述了其数据结构和内存分配策略,尤其是小对象分配的优化,以减少锁竞争,提升高并发场景下的内存管理效率。
摘要由CSDN通过智能技术生成

  

导读

大家可以想看看这条SQL语句思考一下:

SELECT * FROM user WHERE user_name LIKE "%am%" AND age >= 18 AND age <= 24 AND sex = 0 ORDER BY age, user_name LIMIT 0, 50
复制代码

这条SQL使用了快速排序对 age,username 排序,有没有更好的办法,提升排序的性能?

你可能已经发现,这条SQL其实只需要取前50个排好序的用户,但是,上面的执行过程确对表中的1000条记录都进行了排序,如果我只对50记录进行排序,保证这50条记录就是排好序的前50条,从排序算法来看,是不是代价就小很多了呢?那么, 我们怎么做到只对50记录进行排序,同时,这50条记录又刚好是排好序的前50条呢?

学过排序算法的同学可能已经猜到了, 堆排序! 是的,MySQL5.6开始引入了一个新的排序算法,叫做 优先级队列排序 ,该队列使用的就是堆排序,保证只对有限数量n条的记录排序,同时,排序后的结果就是前n条记录。

关于堆排序,计算机相关专业的同学应该比较熟悉,在此,我就不详细讲述了。

PTMalloc

这里,我主要结合《单表数据规模达到多大时进行分表最佳?》这一章中《内存分配》这部分,来详细看一下上面排序过程中,MySQL申请内存的过程:MySQL默认使用ptmalloc内存分配器给进程分配内存。

数据结构

因此,我们先来看一下ptmalloc管理内存块所使用的数据结构:

MySQL调大sort_buffer_size,并发量一大,查询排序为啥又会变慢

分配区

ptmalloc使用一个主分配区和多个动态分配区来管理内存,主分配区与非 主分配区用环形链表进行管理。如上图中的 Main Arena 表示一个主分配区, Dynamic Arena 表示3个动态分配区,它们之间首尾相连,形成环形状。ptmalloc 根据系统对分配区 的争用情况动态增加非主分配区的数量,分配区的数量一旦增加,就不会再减少了。

在《单表数据规模达到多大时进行分表最佳?》中《内存分配》部分,我讲过内存分配器在自身没有可分配内存时,会向Linux系统申请内存,可以申请堆内存,也可以申请文件映射区的内存,所以,对ptmalloc来说,主分配区可以申请堆和文件映射的内存,而动态分配区只能申请文件映射区的内存。

当某一线程需要调用malloc()分配内存空间时,该线程先查看线程私有变量中是否已经 存在一个分配区,如果存在,尝试对该分配区加锁,如果加锁成功,使用该分配区分配内存, 如果失败,该线程搜索循环链表试图获得一个没有加锁的分配区。如果所有的分配区都已经 加锁,那么 malloc()会开辟一个新的分配区,把该分配区加入到全局分配区循环链表并加锁, 然后使用该分配区进行分配内存操作。在释放操作中,线程同样试图获得待释放内存块所在 分配区的锁,如果该分配区正在被别的线程使用,则需要等待直到其他线程释放该分配区的 互斥锁之后才可以进行释放操作。

chunk

MySQL调大sort_buffer_size,并发量一大,查询排序为啥又会变慢

ptmalloc 会统一管理分配区空闲的内存块,当用户进行下一次分配请

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值