2024年9月mysql大量数据查询(敲重点!MySQL数据查询太多会OOM吗)
⑴mysql大量数据查询(敲重点!MySQL数据查询太多会OOM吗
⑵敲重点!MySQL数据查询太多会OOM吗
⑶我的主机内存只有G,现在要全表扫描一个G大表,会不会把DB主机的内存用光?
⑷逻辑备份时,可不就是做整库扫描吗?若这样就会把内存吃光,逻辑备份不是早就挂了?所以大表全表扫描,看起来应该没问题。这是为啥呢?
⑸假设,我们现在要对一个G的InnoDB表db.t,执行一个全表扫描。当然,你要把扫描结果保存在客户端,会使用类似这样的命令:
⑹InnoDB数据保存在主键索引上,所以全表扫描实际上是直接扫描表t的主键索引。这条查询语句由于没有其他判断条件,所以查到的每一行都可以直接放到结果集,然后返回给客户端。
⑺那么,这个“结果集”存在哪里呢?服务端无需保存一个完整结果集。取数据和发数据的流程是这样的:
⑻所以MySQL其实是“边读边发”。这意味着,若客户端接收得慢,会导致MySQL服务端由于结果发不出去,这个事务的执行时间变长。
⑼比如下面这个状态,就是当客户端不读socketreceivebuffer内容时,在服务端showprocesslist看到的结果。
⑽若看到State一直是“Sendingtoclient”,说明服务器端的网络栈写满了。
⑾若客户端使用–quick参数,会使用mysql_use_result方法:读一行处理一行。假设某业务的逻辑较复杂,每读一行数据以后要处理的逻辑若很慢,就会导致客户端要过很久才取下一行数据,可能就会出现上图结果。
⑿因此,对于正常的线上业务来说,若一个查询的返回结果不多,推荐使用mysql_store_result接口,直接把查询结果保存到本地内存。
⒀当然前提是查询返回结果不多。如果太多,因为执行了一个大查询导致客户端占用内存近G,这种情况下就需要改用mysql_use_result接口。
⒁若你在自己负责维护的MySQL里看到很多个线程都处于“Sendingtoclient”,表明你要让业务开发同学优化查询结果,并评估这么多的返回结果是否合理。
⒂若要快速减少处于这个状态的线程的话,可以将_buffer_length设置更大。
⒃有时,实例上看到很多查询语句状态是“Sendingdata”,但查看网络也没什么问题,为什么Sendingdata要这么久?
⒄一个查询语句的状态变化是这样的:
⒅即“Sendingdata”并不一定是指“正在发送数据”,而可能是处于执行器过程中的任意阶段。比如,你可以构造一个锁等待场景,就能看到Sendingdata状态。
⒆Sendingdata状态
⒇可见session是在等锁,状态显示为Sendingdata。
⒈所以,查询的结果是分段发给客户端,因此扫描全表,查询返回大量数据,并不会把内存打爆。
⒉以上是server层的处理逻辑,在InnoDB引擎里又是怎么处理?
⒊InnoDB内存的一个作用,是保存更新的结果,再配合redolog,避免随机写盘。
⒋内存的数据页是在BufferPool(简称为BP)管理,在WAL里BP起加速更新的作用。BP还能加速查询。
⒌而BP对查询的加速效果,依赖于一个重要的指标,即:内存命中率。
⒍可以在showengineinnodbstatus结果中,查看一个系统当前的BP命中率。一般情况下,一个稳定服务的线上系统,要保证响应时间符合要求的话,内存命中率要在%以上。
⒎执行showengineinnodbstatus,可以看到“Bufferpoolhitrate”字样,显示的就是当前的命中率。比如下图命中率,就是%。
⒏若所有查询需要的数据页都能够直接从内存得到,那是最好的,对应命中率%。
⒐InnoDBBufferPool的大小是由参数innodb_buffer_pool_size确定,一般建议设置成可用物理内存的%~%。
⒑在大约十年前,单机的数据量是上百个G,而物理内存是几个G;现在虽然很多服务器都能有G甚至更高的内存,但是单机的数据量却达到了T级别。
⒒所以,innodb_buffer_pool_size小于磁盘数据量很常见。若一个BufferPool满了,而又要从磁盘读入一个数据页,那肯定是要淘汰一个旧数据页的。
⒓使用的最近最少使用(LeastRecentlyUsed,LRU)算法,淘汰最久未使用数据。
⒔InnoDB管理BP的LRU算法,是用链表实现的:
⒕最终就是最久没有被访问的数据页Pm被淘汰。
⒖若此时要做一个全表扫描,会怎样?若要扫描一个G的表,而这个表是一个历史数据表,平时没有业务访问它。
⒗那么,按此算法扫描,就会把当前BP里的数据全部淘汰,存入扫描过程中访问到的数据页的内容。也就是说BP里主要放的是这个历史数据表的数据。
⒘对于一个正在做业务服务的库,这可不行呀。你会看到,BP内存命中率急剧下降,磁盘压力增加,SQL语句响应变慢。
⒙所以,InnoDB不能直接使用原始的LRU。InnoDB对其进行了优化。
⒚InnoDB按:比例把链表分成New区和Old区。图中LRU_old指向的就是old区域的第一个位置,是整个链表的/处。即靠近链表头部的/是New区域,靠近链表尾部的/是old区域。
⒛改进后的LRU算法执行流程:
该策略,就是为了处理类似全表扫描的操作量身定制。还是扫描G历史数据表:
可以看到,这个策略最大的收益,就是在扫描这个大表的过程中,虽然也用到了BP,但对young区完全没有影响,从而保证了BufferPool响应正常业务的查询命中率。
MySQL采用的是边算边发的逻辑,因此对于数据量很大的查询结果来说,不会在server端保存完整的结果集。所以,如果客户端读结果不及时,会堵住MySQL的查询过程,但是不会把内存打爆。
而对于InnoDB引擎内部,由于有淘汰策略,大查询也不会导致内存暴涨。并且,由于InnoDB对LRU算法做了改进,冷数据的全表扫描,对BufferPool的影响也能做到可控。
全表扫描还是比较耗费IO资源的,所以业务高峰期还是不能直接在线上主库执行全表扫描的。
mysql怎么查询很多条数据
假如一条sql语句,你不去限制它的条数的话,默认是将符合条件的所有记录查出来的。例如:select*fromtableAwhereid》;上面一句将会查出tableA表中id》的所有数据;select*fromtableAwhereid》limit;上面一句将会查出tableA表中id》的前条数据,默认以主键顺序排序;
mysql数据量太大怎么查询
告诉你个笨办法,你到data下进入数据库名文件下看看表文件的大小就知道了,一般数据越多文件越大;数据太少不明显。
如果mysql里面的数据过多,查询太慢怎么办
我们有一个SQL,用于找到没有主键/唯一键的表,但是在MySQL.上运行特别慢,怎么办?
我们搭建一个MySQL.的环境,此处省略搭建步骤。
写个简单的脚本,制造一批带主键和不带主键的表:
现在执行以下SQL看看效果:
执行了.s,感觉是非常慢了。
现在用一下DBA三板斧,看看执行计划:
感觉有点惨,由于information_schema.columns是元数据表,没有必要的统计信息。
那我们来showwarnings看看MySQL改写后的SQL:
我们格式化一下SQL:
可以看到MySQL将
selectfromAwhereA.xnotin(selectxfromB)//非关联子查询
selectfromAwherenotexists(selectfromBwhereB.x=a.x)//关联子查询
如果我们自己是MySQL,在执行非关联子查询时,可以使用很简单的策略:
selectfromAwhereA.xnotin(selectxfromBwhere...)//非关联子查询:.扫描B表中的所有记录,找到满足条件的记录,存放在临时表C中,建好索引.扫描A表中的记录,与临时表C中的记录进行比对,直接在索引里比对,
而关联子查询就需要循环迭代:
selectfromAwherenotexists(selectfromBwhereB.x=a.xand...)//关联子查询扫描A表的每一条记录rA:??扫描B表,找到其中的第一条满足rA条件的记录。
显然,关联子查询的扫描成本会高于非关联子查询。
我们希望MySQL能先“缓存“子查询的结果(缓存这一步叫物化,MATERIALIZATION,但MySQL认为不缓存更快,我们就需要给予MySQL一定指导。
可以看到执行时间变成了.s。
我们诊断的关键点如下:
对于information_schema中的元数据表,执行计划不能提供有效信息。
通过查看MySQL改写后的SQL,我们猜测了优化器发生了误判。
我们增加了hint,指导MySQL正确进行优化判断。
但目前我们的实验仅限于猜测,猜中了万事大吉,猜不中就无法做出好的诊断。
Mysql(四)--遍历大量数据
如果我们有一个包含一亿条数据的表需要取出所以数据,如何通过sql取出。我们能想到有四种方式,但是性能效率会有差别,我们此时进行一下分析,判断该如何选择并实践一下查询分析。首先我们发现上面type有range和index区分,key都是primary,rows也有分别,那么我们就来直接看下这几种字段的含义。我们从上面可以看出在大量遍历查询数据的过程中我们应该优先考虑between-and,id》number模式,这样的查询效率会更好一些。
mysql数据库大量查询次数如何优化
MySQL..已经发布,它像往常一样增强了组复制GroupReplication功能。
这篇文章介绍了MySQL..为GroupReplication带来的新功能:
Messagefragmentation(信息碎片化。
GroupReplication目前使用X(一种组通信引擎,特点:原子性,组员状态检测等。每个成员的组复制插件先将信息转发到本地X,再由X最终以相同的顺序将信息传递给每个组成员的GroupReplication插件。
X由单线程实现。当一些成员广播信息过大时,X线程必须花费更多的时间来处理那个大信息。如果成员的X线程忙于处理大信息的时间过长,它可能会去查看其他成员的X实例。例如,忙碌的成员失效。如果是这样,该组可以从该组中驱逐忙碌的成员。
MySQL..新增??group_replication_member_expel_timeout??系统变量,您可以通过它来调整将成员从组中驱逐的时间。例如,怀疑成员失败,但成员实际上忙于处理大信息,给成员足够的时间来完成处理。在这种情况下,是否为成员增加驱逐超时的设置是一种权衡。有可能等了很久,该成员实际真的失效了。
Messagefragmentation(信息碎片化
MySQL..的GroupReplication插件新增用来处理大信息的功能:信息碎片化。
简而言之,您可以为成员的广播信息指定最大值。超过最大值的信息将分段为较小的块传播。
您可以使用?group_replication_munication_max_message_size??系统变量指定允许的信息最大值(默认值为MiB。
让我们用一个例子来解释新功能。图显示了当绿色成员向组广播信息时,新功能是如何处理的。
图对传出信息进行分段
如果信息大小超过用户允许的最大值(group_replication_munication_max_message_size,则该成员会将信息分段为不超过最大值的块。
该成员将每个块广播到该组,即将每个块单独转发到X。
X最终将这些块提供给组成员。下面三张图展示出了中间绿色成员发送大信息时工作的新特征。
图a重新组合传入的信息:第一个片段
成员得出结论,传入的信息实际上是一个更大信息的片段。
成员缓冲传入的片段,因为他们认为片段是仍然不完整的信息的一部分。(片段包含必要的元数据以达到这个结论。
图b重新组合传入的信息:第二个片段
图c重新组合传入的信息:最后一个片段
成员得出结论,传入的信息实际上是一个更大信息的片段。
成员得出结论,传入的片段是最后一个缺失的块,重新组合原始信息,然后对其进行处理,传输完毕。
MySQL..已经发布后,组复制现在可以确保组内交换的信息大小不超过用户定义的阈值。这可以防止组内误判而驱逐成员。
mysql如何批量查询大量数据
select*from表名查询出来所有数据select*from表名where条件根据条件查询select*from表名limit开始下标,每页展示条数分页处理再或者就是取写存储器了,自行百度
[紧急]mysql数据库查询太多怎么办
MYSQL是不能承载那么多数据的列表显示的,如果一下子查那么多数据,不是死机就是等待时间过长,不管是MYSQL数据,其它数据库也一样。你查询的方面要做一些转变,可以去掉*号,查询库表的某一列或几列,不要全表查询,或者你可以采取分页查询,其实你一下子查询多条数据你也看不完,如果分页,则选择或者这样分页,就可以了。切记不要做数据量大的全表查询,想要知道表有多少条数据可以这样查询。seleount(*)fromjieqi_system_users。
mysql数据量较大的表怎么做查询统计效率高
避免全表查询,建立索引。orderby优化你的sql语句。在where子句中尽量避免区域查询,例如不等于,大于小于之类的操作符like语句也会导致全表查询等等
MYSQL对于数据量很多的多表查询,该怎么优化查询
使用连接(JOIN来代替子查询(子查询选择最合适的字段属性使用联合(UNION,以取代临时表使用手动创建使用事务外键索引使用避免使用会非常优化来优化查询