精华内容
下载资源
问答
  • foreach的库原理 默认的foreach的性能缺陷在哪里? 首先,对于每条数据,都要单独去调用一次function,task为每个数据,都要去执行一次function函数。 如果100万条数据,(一个partition),调用100万次。...

    foreach的写库原理
    这里写图片描述
    默认的foreach的性能缺陷在哪里?

    首先,对于每条数据,都要单独去调用一次function,task为每个数据,都要去执行一次function函数。

    如果100万条数据,(一个partition),调用100万次。性能比较差。

    另外一个非常非常重要的一点

    如果每个数据,你都去创建一个数据库连接的话,那么你就得创建100万次数据库连接。

    但是要注意的是,数据库连接的创建和销毁,都是非常非常消耗性能的。虽然我们之前已经用了数据库连接池,只是创建了固定数量的数据库连接。

    你还是得多次通过数据库连接,往数据库(MySQL)发送一条SQL语句,然后MySQL需要去执行这条SQL语句。如果有100万条数据,那么就是100万次发送SQL语句。

    以上两点(数据库连接,多次发送SQL语句),都是非常消耗性能的。
    foreachPartition,在生产环境中,通常来说,都使用foreachPartition来写数据库的
    如下:
    这里写图片描述
    用了foreachPartition算子之后,好处在哪里?

    1、对于我们写的function函数,就调用一次,一次传入一个partition所有的数据

    2、主要创建或者获取一个数据库连接就可以

    3、只要向数据库发送一次SQL语句和多组参数即可
    在实际生产环境中,清一色,都是使用foreachPartition操作;但是有个问题,跟mapPartitions操作一样,如果一个partition的数量真的特别特别大,比如真的是100万,那基本上就不太靠谱了。

    一下子进来,很有可能会发生OOM,内存溢出的问题。

    一组数据的对比:生产环境

    一个partition大概是1千条左右
    用foreach,跟用foreachPartition,性能的提升达到了2~3分钟。

    展开全文
  • HBase最佳实践-性能优化策略

    千次阅读 2017-03-19 21:12:57
    上一篇文章主要介绍了HBase读性能优化的基本套路,本篇文章来说道说道如何诊断HBase写数据的异常问题以及优化写性能。和读相比,HBase写数据流程倒是显得很简单:数据先顺序写入HLog,再写入对应的缓存Memstore,当...

    上一篇文章主要介绍了HBase读性能优化的基本套路,本篇文章来说道说道如何诊断HBase写数据的异常问题以及优化写性能。和读相比,HBase写数据流程倒是显得很简单:数据先顺序写入HLog,再写入对应的缓存Memstore,当Memstore中数据大小达到一定阈值(128M)之后,系统会异步将Memstore中数据flush到HDFS形成小文件。

    HBase数据写入通常会遇到两类问题,一类是写性能较差,另一类是数据根本写不进去。这两类问题的切入点也不尽相同,如下图所示:

    70

    写性能优化切入点

    1. 是否需要写WAL?WAL是否需要同步写入?

    优化原理:数据写入流程可以理解为一次顺序写WAL+一次写缓存,通常情况下写缓存延迟很低,因此提升写性能就只能从WAL入手。WAL机制一方面是为了确保数据即使写入缓存丢失也可以恢复,另一方面是为了集群之间异步复制。默认WAL机制开启且使用同步机制写入WAL。首先考虑业务是否需要写WAL,通常情况下大多数业务都会开启WAL机制(默认),但是对于部分业务可能并不特别关心异常情况下部分数据的丢失,而更关心数据写入吞吐量,比如某些推荐业务,这类业务即使丢失一部分用户行为数据可能对推荐结果并不构成很大影响,但是对于写入吞吐量要求很高,不能造成数据队列阻塞。这种场景下可以考虑关闭WAL写入,写入吞吐量可以提升2x~3x。退而求其次,有些业务不能接受不写WAL,但可以接受WAL异步写入,也是可以考虑优化的,通常也会带来1x~2x的性能提升。

    优化推荐:根据业务关注点在WAL机制与写入吞吐量之间做出选择

    其他注意点:对于使用Increment操作的业务,WAL可以设置关闭,也可以设置异步写入,方法同Put类似。相信大多数Increment操作业务对WAL可能都不是那么敏感~

    2. Put是否可以同步批量提交?

    优化原理:HBase分别提供了单条put以及批量put的API接口,使用批量put接口可以减少客户端到RegionServer之间的RPC连接数,提高写入性能。另外需要注意的是,批量put请求要么全部成功返回,要么抛出异常。

    优化建议:使用批量put进行写入请求

    3. Put是否可以异步批量提交?

    优化原理:业务如果可以接受异常情况下少量数据丢失的话,还可以使用异步批量提交的方式提交请求。提交分为两阶段执行:用户提交写请求之后,数据会写入客户端缓存,并返回用户写入成功;当客户端缓存达到阈值(默认2M)之后批量提交给RegionServer。需要注意的是,在某些情况下客户端异常的情况下缓存数据有可能丢失。

    优化建议:在业务可以接受的情况下开启异步批量提交

    使用方式:setAutoFlush(false)

    4. Region是否太少?

    优化原理:当前集群中表的Region个数如果小于RegionServer个数,即Num(Region of Table) < Num(RegionServer),可以考虑切分Region并尽可能分布到不同RegionServer来提高系统请求并发度,如果Num(Region of Table) > Num(RegionServer),再增加Region个数效果并不明显。

    优化建议:在Num(Region of Table) < Num(RegionServer)的场景下切分部分请求负载高的Region并迁移到其他RegionServer;

    5. 写入请求是否不均衡?

    优化原理:另一个需要考虑的问题是写入请求是否均衡,如果不均衡,一方面会导致系统并发度较低,另一方面也有可能造成部分节点负载很高,进而影响其他业务。分布式系统中特别害怕一个节点负载很高的情况,一个节点负载很高可能会拖慢整个集群,这是因为很多业务会使用Mutli批量提交读写请求,一旦其中一部分请求落到该节点无法得到及时响应,就会导致整个批量请求超时。因此不怕节点宕掉,就怕节点奄奄一息!

    优化建议:检查RowKey设计以及预分区策略,保证写入请求均衡。

    6. 写入KeyValue数据是否太大?

    KeyValue大小对写入性能的影响巨大,一旦遇到写入性能比较差的情况,需要考虑是否由于写入KeyValue数据太大导致。KeyValue大小对写入性能影响曲线图如下:

    72

    图中横坐标是写入的一行数据(每行数据10列)大小,左纵坐标是写入吞吐量,右坐标是写入平均延迟(ms)。可以看出随着单行数据大小不断变大,写入吞吐量急剧下降,写入延迟在100K之后急剧增大。

    说到这里,有必要和大家分享两起在生产线环境因为业务KeyValue较大导致的严重问题,一起是因为大字段业务写入导致其他业务吞吐量急剧下降,另一起是因为大字段业务scan导致RegionServer宕机。

    案件一:大字段写入导致其他业务吞吐量急剧下降

    部分业务反馈集群写入忽然变慢、数据开始堆积的情况,查看集群表级别的数据读写QPS监控,发现问题的第一个关键点:业务A开始写入之后整个集群其他部分业务写入QPS都几乎断崖式下跌,初步怀疑黑手就是业务A。

    下图是当时业务A的写入QPS(事后发现脑残忘了截取其他表QPS断崖式下跌的惨象),但是第一感觉是QPS并不高啊,凭什么去影响别人!

    73

    于是就继续查看其他监控信息,首先确认系统资源(主要是IO)并没有到达瓶颈,其次确认了写入的均衡性,直至看到下图,才追踪到影响其他业务写入的第二个关键点:RegionServer的handler(配置150)被残暴耗尽:

    74

    对比上面两张图,是不是发现出奇的一致,那就可以基本确认是由于该业务写入导致这台RegionServer的handler被耗尽,进而其他业务拿不到handler,自然写不进去。那问题来了,为什么会这样?正常情况下handler在处理完客户端请求之后会立马释放,唯一的解释是这些请求的延迟实在太大。

    试想,我们去汉堡店排队买汉堡,有150个窗口服务,正常情况下大家买一个很快,这样150个窗口可能只需要50个服务。假设忽然来了一批大汉,要定制超大汉堡,好了,所有的窗口都工作起来,而且因为大汉堡不好制作导致服务很慢,这样必然会导致其他排队的用户长时间等待,直至超时。

    可回头一想这可是写请求啊,怎么会有这么大的请求延迟!和业务方沟通之后确认该表主要存储语料库文档信息,都是平均100K左右的数据,是不是已经猜到了结果,没错,就是因为这个业务KeyValue太大导致。KeyValue太大会导致HLog文件写入频繁切换、flush以及compaction频繁触发,写入性能急剧下降。

    目前针对这种较大KeyValue写入性能较差的问题还没有直接的解决方案,好在社区已经意识到这个问题,在接下来即将发布的下一个大版本HBase 2.0.0版本会针对该问题进行深入优化,详见HBase MOB,优化后用户使用HBase存储文档、图片等二进制数据都会有极佳的性能体验。

    案件二:大字段scan导致RegionServer宕机

    案件现场:有段时间有个0.98集群的RegionServer经常频繁宕机,查看日志是由于”java.lang.OutOfMemoryError: Requested array size exceeds VM limit”,如下图所示:

    76

    原因分析:通过查看源码以及相关文档,确认该异常发生在scan结果数据回传给客户端时由于数据量太大导致申请的array大小超过JVM规定的最大值( Interge.Max_Value-2)。造成该异常的两种最常见原因分别是:

    • 表列太宽(几十万列或者上百万列),并且scan返回没有对列数量做任何限制,导致一行数据就可能因为包含大量列而数据超过array大小阈值
    • KeyValue太大,并且scan返回没有对返回结果大小做任何限制,导致返回数据结果大小超过array大小阈值

    有的童鞋就要提问啦,说如果已经对返回结果大小做了限制,在表列太宽的情况下是不是就可以不对列数量做限制呢。这里需要澄清一下,如果不对列数据做限制,数据总是一行一行返回的,即使一行数据大小大于设置的返回结果限制大小,也会返回完整的一行数据。在这种情况下,如果这一行数据已经超过array大小阈值,也会触发OOM异常。

    解决方案:目前针对该异常有两种解决方案,其一是升级集群到1.0,问题都解决了。其二是要求客户端访问的时候对返回结果大小做限制(scan.setMaxResultSize(2*1024*1024))、并且对列数量做限制(scan.setBatch(100)),当然,0.98.13版本以后也可以对返回结果大小在服务器端进行限制,设置参数hbase.server.scanner.max.result.size即可

    写异常问题检查点

    上述几点主要针对写性能优化进行了介绍,除此之外,在一些情况下还会出现写异常,一旦发生需要考虑下面两种情况(GC引起的不做介绍):

    Memstore设置是否会触发Region级别或者RegionServer级别flush操作?

    问题解析:以RegionServer级别flush进行解析,HBase设定一旦整个RegionServer上所有Memstore占用内存大小总和大于配置文件中upperlimit时,系统就会执行RegionServer级别flush,flush算法会首先按照Region大小进行排序,再按照该顺序依次进行flush,直至总Memstore大小低至lowerlimit。这种flush通常会block较长时间,在日志中会发现“Memstore is above high water mark and block 7452 ms”,表示这次flush将会阻塞7s左右。

    问题检查点:

    • Region规模与Memstore总大小设置是否合理?如果RegionServer上Region较多,而Memstore总大小设置的很小(JVM设置较小或者upper.limit设置较小),就会触发RegionServer级别flush。集群规划相关内容可以参考文章《》
    • 列族是否设置过多,通常情况下表列族建议设置在1~3个之间,最好一个。如果设置过多,会导致一个Region中包含很多Memstore,导致更容易触到高水位upperlimit

    Store中HFile数量是否大于配置参数blockingStoreFile?

    问题解析:对于数据写入很快的集群,还需要特别关注一个参数:hbase.hstore.blockingStoreFiles,此参数表示如果当前hstore中文件数大于该值,系统将会强制执行compaction操作进行文件合并,合并的过程会阻塞整个hstore的写入。通常情况下该场景发生在数据写入很快的情况下,在日志中可以发现”Waited 3722ms on a compaction to clean up ‘too many store  files

    问题检查点:

    • 参数设置是否合理?hbase.hstore.compactionThreshold表示启动compaction的最低阈值,该值不能太大,否则会积累太多文件,一般建议设置为5~8左右。hbase.hstore.blockingStoreFiles默认设置为7,可以适当调大一些。

    写性能还能再提高么?

    上文已经从写性能优化以及写异常诊断两个方面对HBase中数据写入可能的问题进行了详细的解释,相信在0.98版本的基础上对写入来说已经是最好的解决方案了。但是有些业务可能依然觉得不够快,毕竟”更快”是所有存储系统活着的动力,那还有提高空间吗?当然,接下来简单介绍HBase之后版本对写性能优化的两点核心改进:

    • Utilize Flash storage for WAL(HBASE-12848)

    这个特性意味着可以将WAL单独置于SSD上,这样即使在默认情况下(WALSync),写性能也会有很大的提升。需要注意的是,该特性建立在HDFS 2.6.0+的基础上,HDFS以前版本不支持该特性。具体可以参考官方jira:https://issues.apache.org/jira/browse/HBASE-12848

    • Multiple WALs(HBASE-14457)

    该特性也是对WAL进行改造,当前WAL设计为一个RegionServer上所有Region共享一个WAL,可以想象在写入吞吐量较高的时候必然存在资源竞争,降低整体性能。针对这个问题,社区小伙伴(阿里巴巴大神)提出Multiple WALs机制,管理员可以为每个Namespace下的所有表设置一个共享WAL,通过这种方式,写性能大约可以提升20%~40%左右。具体可以参考官方jira:https://issues.apache.org/jira/browse/HBASE-14457

    好了,这篇文章和大家一起分享了个人对HBase写入性能优化以及写入异常问题的一些理解,如有纰漏,还望指正!另外,如果大家有任何关于此话题的案例也很欢迎一起讨论~

    展开全文
  • HBase性能优化策略

    千次阅读 2017-11-13 10:20:21
    一 HBase写入性能优化 1.1 是否需要WAL? WAL是否需要同步? WAL机制可以确保数据即使写入缓存的数据丢失了,也可以恢复;另外是为了集群之间的异步复制。默认WAL机制开启,且使用同步机制写入WAL. 我们可以...

    HBase写入通常会遇到两种问题:

    # 写的性能很差

    # 根本写不进去


    一 HBase写入性能优化

    1.1 是否需要写WAL? WAL是否需要同步写?

    WAL机制可以确保数据即使写入缓存的数据丢失了,也可以恢复;另外是为了集群之间的异步复制。默认WAL机制开启,且使用同步机制写入WAL. 我们可以考虑是否需要写入WAL,通常大多数企业业务都会开启,但是对于部分业务可能并不特别关心异常情况下部分数据的丢失,而更关心数据写入吞吐量,不能造成数据队列堵塞。这种场景可以选择关闭WAL写入;或者看能否接受异步写入

    所以应该根据业务关注点在WAL机制和写入吞吐量之间做一个抉择

     

    1.2 PUT是否可以同步批量提交

    HBase分别提供了单条put以及批量put的API接口,使用批量put接口可以减少客户端到RegionServer之间的RPC连接数,提高写入性能。另外需要注意的是,批量put请求要么全部成功返回,要么抛出异常。

    所以建议使用批量PUT写入请求

     

    1.3 PUT是否可以异步批量提交

    业务如果可以接受异常情况下少量数据丢失的话,还可以使用异步批量提交的方式提交请求。提交分为两阶段执行:用户提交写请求之后,数据会写入客户端缓存,并返回用户写入成功;当客户端缓存达到阈值(默认2M)之后批量提交给RegionServer。需要注意的是,在某些情况下客户端异常的情况下缓存数据有可能丢失。

     

    所以在业务可以接受的情况下开启异步批量提交


    1.4 Region数量少于RegionServer数量

    当前集群中表的Region个数如果小于RegionServer个数,可以考虑切分Region并尽可能分布到不同RegionServer来提高系统请求并发度,如果Num(Region of Table) > Num(RegionServer),再增加Region个数效果并不明显

     

    所以在Num(Region of Table) <Num(RegionServer)的场景下切分部分请求负载高的Region并迁移到其他RegionServer

     

    1.5 写入请求是否均衡

    另一个需要考虑的问题是写入请求是否均衡,如果不均衡,一方面会导致系统并发度较低,另一方面也有可能造成部分节点负载很高,进而影响其他业务。分布式系统中特别害怕一个节点负载很高的情况,一个节点负载很高可能会拖慢整个集群,这是因为很多业务会使用Mutli批量提交读写请求,一旦其中一部分请求落到该节点无法得到及时响应,就会导致整个批量请求超时。

     

    所以建议检查Rowkey 预分区策略

     

    1.6 写入的KeyValue数据是否太大

    KeyValue大小对写入性能的影响巨大,一旦遇到写入性能比较差的情况,需要考虑是否由于写入KeyValue数据太大导致。KeyValue大小对写入性能影响曲线图如下:



    KeyValue太大会导致HLog文件写入频繁切换、flush以及compaction频繁触发,写入性能急剧下降。

    如果是大字段scan导致RegionServer宕机,那么客户端在访问的时候对返回结果大小做限制(scan.setMaxResultSize(2*1024*1024)),并且对列数量做限制(scan.setBatch(100))

       

    二 写异常问题

    2.1 MemStore相关的配置是否合理

    以RegionServer级别flush进行解析,HBase设定一旦整个RegionServer上所有Memstore占用内存大小总和大于配置文件中upperlimit时,系统就会执行RegionServer级别flush,flush算法会首先按照Region大小进行排序,再按照该顺序依次进行flush,直至总Memstore大小低至lowerlimit

     

    Region规模与Memstore总大小设置是否合理?如果RegionServer上Region较多,而Memstore总大小设置的很小(JVM设置较小或者upper.limit设置较小),就会触发RegionServer级别flush

     

    列族是否设置过多,通常情况下表列族建议设置在1~3个之间,最好一个。如果设置过多,会导致一个Region中包含很多Memstore,导致更容易触到高水位upperlimit

     

    2.2 Store中HFile数量是否大于配置参数blockingStoreFile

    对于数据写入很快的集群,还需要特别关注一个参数:hbase.hstore.blockingStoreFiles,此参数表示如果当前hstore中文件数大于该值,系统将会强制执行compaction操作进行文件合并,合并的过程会阻塞整个hstore的写入。通常情况下该场景发生在数据写入很快的情况下,在日志中可以发现”Waited 3722ms on a compaction to clean up ‘too many store files“

     

    参数设置是否合理?hbase.hstore.compactionThreshold表示启动compaction的最低阈值,该值不能太大,否则会积累太多文件,一般建议设置为5~8左右。hbase.hstore.blockingStoreFiles默认设置为7,可以适当调大一些。


    展开全文
  • 如何优化MySQL千万级大表,我了6000字的解读

    万次阅读 多人点赞 2019-10-21 20:03:03
    千万级大表如何优化,这是一个很有技术含量的问题,通常我们的直觉思维都会跳转到拆分或者数据分区,在此我想做一些补充和梳理,想和大家做一些这方面的经验总结,也欢迎大家提出建议。 从一开始脑海里开始也是...

    这是学习笔记的第 2138 篇文章

      640?wx_fmt=gif

    千万级大表如何优化,这是一个很有技术含量的问题,通常我们的直觉思维都会跳转到拆分或者数据分区,在此我想做一些补充和梳理,想和大家做一些这方面的经验总结,也欢迎大家提出建议。 

    从一开始脑海里开始也是火光四现,到不断的自我批评,后来也参考了一些团队的经验,我整理了下面的大纲内容。

    640?wx_fmt=png

    既然要吃透这个问题,我们势必要回到本源,我把这个问题分为三部分:

    “千万级”,“大表”,“优化”,

    也分别对应我们在图中标识的

    “数据量”,“对象”和“目标”。

    我来逐步展开说明一下,从而给出一系列的解决方案。 

    1.数据量:千万级

    千万级其实只是一个感官的数字,就是我们印象中的数据量大。 这里我们需要把这个概念细化,因为随着业务和时间的变化,数据量也会有变化,我们应该是带着一种动态思维来审视这个指标,从而对于不同的场景我们应该有不同的处理策略。

     

    1) 数据量为千万级,可能达到亿级或者更高

    通常是一些数据流水,日志记录的业务,里面的数据随着时间的增长会逐步增多,超过千万门槛是很容易的一件事情。

    2) 数据量为千万级,是一个相对稳定的数据量

    如果数据量相对稳定,通常是在一些偏向于状态的数据,比如有1000万用户,那么这些用户的信息在表中都有相应的一行数据记录,随着业务的增长,这个量级相对是比较稳定的。

    3) 数据量为千万级,不应该有这么多的数据

    这种情况是我们被动发现的居多,通常发现的时候已经晚了,比如你看到一个配置表,数据量上千万;或者说一些表里的数据已经存储了很久,99%的数据都属于过期数据或者垃圾数据。

    数据量是一个整体的认识,我们需要对数据做更近一层的理解,这就可以引出第二个部分的内容。 

    2.对象:数据表

    数据操作的过程就好比数据库中存在着多条管道,这些管道中都流淌着要处理的数据,这些数据的用处和归属是不一样的。

    一般根据业务类型把数据分为三种:

    (1)流水型数据

    流水型数据是无状态的,多笔业务之间没有关联,每次业务过来的时候都会产生新的单据,比如交易流水、支付流水,只要能插入新单据就能完成业务,特点是后面的数据不依赖前面的数据,所有的数据按时间流水进入数据库。

    (2)状态型数据

    状态型数据是有状态的,多笔业务之间依赖于有状态的数据,而且要保证该数据的准确性,比如充值时必须要拿到原来的余额,才能支付成功。

    (3)配置型数据

    此类型数据数据量较小,而且结构简单,一般为静态数据,变化频率很低。

    至此,我们可以对整体的背景有一个认识了,如果要做优化,其实要面对的是这样的3*3的矩阵,如果要考虑表的读写比例(读多写少,读少写多...),那么就会是3*3*4=24种,显然做穷举是不显示的,而且也完全没有必要,可以针对不同的数据存储特性和业务特点来指定不同的业务策略。 

    对此我们采取抓住重点的方式,把常见的一些优化思路梳理出来,尤其是里面的核心思想,也是我们整个优化设计的一把尺子,而难度决定了我们做这件事情的动力和风险。

    数据量增长情况

    数据表类型

    业务特点

    优化核心思想

    优化难度

    数据量为千万级,是一个相对稳定的数据量

    状态表

    OLTP业务方向

    能不拆就不拆读需求水平扩展

    ****

    数据量为千万级,可能达到亿级或者更高

    流水表

    OLTP业务的历史记录

    业务拆分,面向分布式存储设计

    ****

    OLAP业务统计数据源

    设计数据统计需求存储的分布式扩展

    ***

    数据量为千万级,不应该有这么多的数据

    配置表

    通用业务

    小而简,避免大一统

    *

    而对于优化方案,我想采用面向业务的维度来进行阐述。 

    3.目标:优化

    在这个阶段,我们要说优化的方案了,总结的有点多,相对来说是比较全了。

    整体分为五个部分:

    640?wx_fmt=png

    其实我们通常所说的分库分表等方案只是其中的一小部分,如果展开之后就比较丰富了。

    640?wx_fmt=png

    其实不难理解,我们要支撑的表数据量是千万级别,相对来说是比较大了,DBA要维护的表肯定不止一张,如何能够更好的管理,同时在业务发展中能够支撑扩展,同时保证性能,这是摆在我们面前的几座大山。

    我们分别来说一下这五类改进方案:

    优化设计方案1.规范设计

    在此我们先提到的是规范设计,而不是其他高大上的设计方案。

    黑格尔说:秩序是自由的第一条件。在分工协作的工作场景中尤其重要,否则团队之间互相牵制太多,问题多多。

    规范设计我想提到如下的几个规范,其实只是属于开发规范的一部分内容,可以作为参考。

    640?wx_fmt=png

    规范的本质不是解决问题,而是有效杜绝一些潜在问题,对于千万级大表要遵守的规范,我梳理了如下的一些细则,基本可以涵盖我们常见的一些设计和使用问题,比如表的字段设计不管三七二十一,都是varchar(500),其实是很不规范的一种实现方式,我们来展开说一下这几个规范。

    1)配置规范

    (1)MySQL数据库默认使用InnoDB存储引擎。

    (2)保证字符集设置统一,MySQL数据库相关系统、数据库、表的字符集使都用UTF8,应用程序连接、展示等可以设置字符集的地方也都统一设置为UTF8字符集。

    注:UTF8格式是存储不了表情类数据,需要使用UTF8MB4,可在MySQL字符集里面设置。在8.0中已经默认为UTF8MB4,可以根据公司的业务情况进行统一或者定制化设置。

    (3)MySQL数据库的事务隔离级别默认为RR(Repeatable-Read),建议初始化时统一设置为RC(Read-Committed),对于OLTP业务更适合。

    (4)数据库中的表要合理规划,控制单表数据量,对于MySQL数据库来说,建议单表记录数控制在2000W以内。

    (5)MySQL实例下,数据库、表数量尽可能少;数据库一般不超过50个,每个数据库下,数据表数量一般不超过500个(包括分区表)。

    2)建表规范

    (1)InnoDB禁止使用外键约束,可以通过程序层面保证。

    (2)存储精确浮点数必须使用DECIMAL替代FLOAT和DOUBLE。

    (3)整型定义中无需定义显示宽度,比如:使用INT,而不是INT(4)。

    (4)不建议使用ENUM类型,可使用TINYINT来代替。

    (5)尽可能不使用TEXT、BLOB类型,如果必须使用,建议将过大字段或是不常用的描述型较大字段拆分到其他表中;另外,禁止用数据库存储图片或文件。

    (6)存储年时使用YEAR(4),不使用YEAR(2)。

    (7)建议字段定义为NOT NULL。

    (8)建议DBA提供SQL审核工具,建表规范性需要通过审核工具审核后

    3)命名规范

    (1)库、表、字段全部采用小写。

    (2)库名、表名、字段名、索引名称均使用小写字母,并以“_”分割。

    (3)库名、表名、字段名建议不超过12个字符。(库名、表名、字段名支持最多64个字符,但为了统一规范、易于辨识以及减少传输量,统一不超过12字符)

    (4)库名、表名、字段名见名知意,不需要添加注释。

    对于对象命名规范的一个简要总结如下表4-1所示,供参考。

    命名列表

    对象中文名称

    对象英文全称

    MySQL对象简写

    视图

    view

    view_

    函数

    function

    func_

    存储过程

    procedure

    proc_

    触发器

    trigger

    trig_

    普通索引

    index

    idx_

    唯一索引

    unique index

    uniq_

    主键索引

    primary key

    pk_

    4)索引规范

    (1)索引建议命名规则:idx_col1_col2[_colN]、uniq_col1_col2[_colN](如果字段过长建议采用缩写)。

    (2)索引中的字段数建议不超过5个。

    (3)单张表的索引个数控制在5个以内。

    (4)InnoDB表一般都建议有主键列,尤其在高可用集群方案中是作为必须项的。

    (5)建立复合索引时,优先将选择性高的字段放在前面。

    (6)UPDATE、DELETE语句需要根据WHERE条件添加索引。

    (7)不建议使用%前缀模糊查询,例如LIKE “%weibo”,无法用到索引,会导致全表扫描。

    (8)合理利用覆盖索引,例如:

    (9)SELECT email,uid FROM user_email WHERE uid=xx,如果uid不是主键,可以创建覆盖索引idx_uid_email(uid,email)来提高查询效率。

    (10)避免在索引字段上使用函数,否则会导致查询时索引失效。

    (11)确认索引是否需要变更时要联系DBA。

    5)应用规范

    (1)避免使用存储过程、触发器、自定义函数等,容易将业务逻辑和DB耦合在一起,后期做分布式方案时会成为瓶颈。

    (2)考虑使用UNION ALL,减少使用UNION,因为UNION ALL不去重,而少了排序操作,速度相对比UNION要快,如果没有去重的需求,优先使用UNION ALL。

    (3)考虑使用limit N,少用limit M,N,特别是大表或M比较大的时候。

    (4)减少或避免排序,如:group by语句中如果不需要排序,可以增加order by null。

    (5)统计表中记录数时使用COUNT(*),而不是COUNT(primary_key)和COUNT(1);InnoDB表避免使用COUNT(*)操作,计数统计实时要求较强可以使用Memcache或者Redis,非实时统计可以使用单独统计表,定时更新。

    (6)做字段变更操作(modify column/change column)的时候必须加上原有的注释属性,否则修改后,注释会丢失。

    (7)使用prepared statement可以提高性能并且避免SQL注入。

    (8)SQL语句中IN包含的值不应过多。

    (9)UPDATE、DELETE语句一定要有明确的WHERE条件。

    (10)WHERE条件中的字段值需要符合该字段的数据类型,避免MySQL进行隐式类型转化。

    (11)SELECT、INSERT语句必须显式的指明字段名称,禁止使用SELECT * 或是INSERT INTO table_name values()。

    (12)INSERT语句使用batch提交(INSERT INTO table_name VALUES(),(),()……),values的个数不应过多。

    优化设计方案2:业务层优化

    业务层优化应该是收益最高的优化方式了,而且对于业务层完全可见,主要有业务拆分,数据拆分和两类常见的优化场景(读多写少,读少写多)

    640?wx_fmt=png

    1)业务拆分

    ü 将混合业务拆分为独立业务

    ü 将状态和历史数据分离

    业务拆分其实是把一个混合的业务剥离成为更加清晰的独立业务,这样业务1,业务2。。。独立的业务使得业务总量依旧很大,但是每个部分都是相对独立的,可靠性依然有保证。

    对于状态和历史数据分离,我可以举一个例子来说明。

    例如:我们有一张表Account,假设用户余额为100。

    640?wx_fmt=png

    我们需要在发生数据变更后,能够追溯数据变更的历史信息,如果对账户更新状态数据,增加100的余额,这样余额为200。

    这个过程可能对应一条update语句,一条insert语句。

    对此我们可以改造为两个不同的数据源,account和account_hist

    在account_hist中就会是两条insert记录,如下:

    640?wx_fmt=png

    而在account中则是一条update语句,如下:

    640?wx_fmt=png

    这也是一种很基础的冷热分离,可以大大减少维护的复杂度,提高业务响应效率。

    2)数据拆分

    2.1 按照日期拆分,这种使用方式比较普遍,尤其是按照日期维度的拆分,其实在程序层面的改动很小,但是扩展性方面的收益很大。

    • 数据按照日期维度拆分,如test_20191021

    • 数据按照周月为维度拆分,如test_201910

    • 数据按照季度,年维度拆分,如test_2019

    2.2 采用分区模式,分区模式也是常见的使用方式,采用hash,range等方式会多一些,在MySQL中我是不大建议使用分区表的使用方式,因为随着存储容量的增长,数据虽然做了垂直拆分,但是归根结底,数据其实难以实现水平扩展,在MySQL中是有更好的扩展方式。

    2.3 读多写少优化场景

    采用缓存,采用Redis技术,将读请求打在缓存层面,这样可以大大降低MySQL层面的热点数据查询压力。

    2.4 读少写多优化场景,可以采用三步走:

    1) 采用异步提交模式,异步对于应用层来说最直观的就是性能的提升,产生最少的同步等待。

    2) 使用队列技术,大量的写请求可以通过队列的方式来进行扩展,实现批量的数据写入。

    3) 降低写入频率,这个比较难理解,我举个例子

    对于业务数据,比如积分类,相比于金额来说业务优先级略低的场景,如果数据的更新过于频繁,可以适度调整数据更新的范围(比如从原来的每分钟调整为10分钟)来减少更新的频率。

    例如:更新状态数据,积分为200,如下图所示

    640?wx_fmt=png

    可以改造为,如下图所示。

    640?wx_fmt=png

    如果业务数据在短时间内更新过于频繁,比如1分钟更新100次,积分从100到10000,则可以根据时间频率批量提交。

    例如:更新状态数据,积分为100,如下图所示。

    640?wx_fmt=png

    无需生成100个事务(200条SQL语句)可以改造为2条SQL语句,如下图所示。

    640?wx_fmt=png

    对于业务指标,比如更新频率细节信息,可以根据具体业务场景来讨论决定。

    优化设计方案3:架构层优化

    架构层优化其实就是我们认为的那种技术含量很高的工作,我们需要根据业务场景在架构层面引入一些新的花样来。

    640?wx_fmt=png

    3.1.系统水平扩展场景

    3.1.1采用中间件技术,可以实现数据路由,水平扩展,常见的中间件有MyCAT,ShardingSphere,ProxySQL等

    640?wx_fmt=jpeg

    3.1.2 采用读写分离技术,这是针对读需求的扩展,更侧重于状态表,在允许一定延迟的情况下,可以采用多副本的模式实现读需求的水平扩展,也可以采用中间件来实现,如MyCAT,ProxySQL,MaxScale,MySQL Router等

    640?wx_fmt=png

    3.1.3 采用负载均衡技术,常见的有LVS技术或者基于域名服务的Consul技术等

    3.2.兼顾OLTP+OLAP的业务场景,可以采用NewSQL,优先兼容MySQL协议的HTAP技术栈,如TiDB

    3.3.离线统计的业务场景,有几类方案可供选择。

    3.3.1 采用NoSQL体系,主要有两类,一类是适合兼容MySQL协议的数据仓库体系,常见的有Infobright或者ColumnStore,另外一类是基于列式存储,属于异构方向,如HBase技术

    3.3.2 采用数仓体系,基于MPP架构,如使用Greenplum统计,如T+1统计

    优化设计方案4:数据库优化

    数据库优化,其实可打的牌也不少,但是相对来说空间没有那么大了,我们来逐个说一下。

    640?wx_fmt=png

    4.1 事务优化

    根据业务场景选择事务模型,是否是强事务依赖

    对于事务降维策略,我们来举出几个小例子来。

    4.1.1 降维策略1:存储过程调用转换为透明的SQL调用

    对于新业务而言,使用存储过程显然不是一个好主意,MySQL的存储过程和其他商业数据库相比,功能和性能都有待验证,而且在目前轻量化的业务处理中,存储过程的处理方式太“重”了。

    有些应用架构看起来是按照分布式部署的,但在数据库层的调用方式是基于存储过程,因为存储过程封装了大量的逻辑,难以调试,而且移植性不高,这样业务逻辑和性能压力都在数据库层面了,使得数据库层很容易成为瓶颈,而且难以实现真正的分布式。

    所以有一个明确的改进方向就是对于存储过程的改造,把它改造为SQL调用的方式,可以极大地提高业务的处理效率,在数据库的接口调用上足够简单而且清晰可控。

    4.1.2 降维策略2:DDL操作转换为DML操作

    有些业务经常会有一种紧急需求,总是需要给一个表添加字段,搞得DBA和业务同学都挺累,可以想象一个表有上百个字段,而且基本都是name1,name2……name100,这种设计本身就是有问题的,更不用考虑性能了。究其原因,是因为业务的需求动态变化,比如一个游戏装备有20个属性,可能过了一个月之后就增加到了40个属性,这样一来,所有的装备都有40个属性,不管用没用到,而且这种方式也存在诸多的冗余。

    我们在设计规范里面也提到了一些设计的基本要素,在这些基础上需要补充的是,保持有限的字段,如果要实现这些功能的扩展,其实完全可以通过配置化的方式来实现,比如把一些动态添加的字段转换为一些配置信息。配置信息可以通过DML的方式进行修改和补充,对于数据入口也可以更加动态、易扩展。

    4.1.3 降维策略3:Delete操作转换为高效操作

    有些业务需要定期来清理一些周期性数据,比如表里的数据只保留一个月,那么超出时间范围的数据就要清理掉了,而如果表的量级比较大的情况下,这种Delete操作的代价实在太高,我们可以有两类解决方案来把Delete操作转换为更为高效的方式。 

    第一种是根据业务建立周期表,比如按照月表、周表、日表等维度来设计,这样数据的清理就是一个相对可控而且高效的方式了。 

    第二种方案是使用MySQL rename的操作方式,比如一张2千万的大表要清理99%的数据,那么需要保留的1%的数据我们可以很快根据条件过滤补录,实现“移形换位”。

    4.2 SQL优化

    其实相对来说需要的极简的设计,很多点都在规范设计里面了,如果遵守规范,八九不离十的问题都会杜绝掉,在此补充几点:

    4.2.1 SQL语句简化,简化是SQL优化的一大利器,因为简单,所以优越。

    4.2.2 尽可能避免或者杜绝多表复杂关联,大表关联是大表处理的噩梦,一旦打开了这个口子,越来越多的需求需要关联,性能优化就没有回头路了,更何况大表关联是MySQL的弱项,尽管Hash Join才推出,不要像掌握了绝对大杀器一样,在商业数据库中早就存在,问题照样层出不穷。

    4.2.3 SQL中尽可能避免反连接,避免半连接,这是优化器做得薄弱的一方面,什么是反连接,半连接?其实比较好理解,举个例子,not in ,not exists就是反连接,in,exists就是半连接,在千万级大表中出现这种问题,性能是几个数量级的差异。 

    4.3 索引优化

    应该是大表优化中需要把握的一个度。

    4.3.1 首先必须有主键,规范设计中第一条就是,此处不接收反驳。

    4.3.2 其次,SQL查询基于索引或者唯一性索引,使得查询模型尽可能简单。

    4.3.3 最后,尽可能杜绝范围数据的查询,范围扫描在千万级大表情况下还是尽可能减少。

    优化设计方案4:管理优化

    这部分应该是在所有的解决方案中最容易被忽视的部分了,我放在最后,在此也向运维同事致敬,总是为很多认为本应该正常的问题尽职尽责(背锅)。

    640?wx_fmt=png

    千万级大表的数据清理一般来说是比较耗时的,在此建议在设计中需要完善冷热数据分离的策略,可能听起来比较拗口,我来举一个例子,把大表的Drop 操作转换为可逆的DDL操作。

    Drop操作是默认提交的,而且是不可逆的,在数据库操作中都是跑路的代名词,MySQL层面目前没有相应的Drop操作恢复功能,除非通过备份来恢复,但是我们可以考虑将Drop操作转换为一种可逆的DDL操作。

    MySQL中默认每个表有一个对应的ibd文件,其实可以把Drop操作转换为一个rename操作,即把文件从testdb迁移到testdb_arch下面;从权限上来说,testdb_arch是业务不可见的,rename操作可以平滑的实现这个删除功能,如果在一定时间后确认可以清理,则数据清理对于已有的业务流程是不可见的,如下图所示。

    640?wx_fmt=png

    此外,还有两个额外建议,一个是对于大表变更,尽可能考虑低峰时段的在线变更,比如使用pt-osc工具或者是维护时段的变更,就不再赘述了。

    最后总结一下,其实就是一句话:

    千万级大表的优化是根据业务场景,以成本为代价进行优化的,绝对不是孤立的一个层面的优化。

    近期热文:

    个人新书 《MySQL DBA工作笔记》

    个人公众号:jianrong-notes

    QQ群号:763628645

    QQ群二维码如下,个人微信号:jeanron100, 添加请注明:姓名+地区+职位,否则不予通过

    640?wx_fmt=png640?wx_fmt=png

    在看,让更多人看到

    展开全文
  • 数据库优化之读写分离

    万次阅读 2016-11-02 15:19:43
    开启mysql的慢查询,查询是否是某个SQL语句占用过多资源,如果是的话,可以对SQL语句进行优化,比如优化 insert 语句、优化 group by 语句、优化 order by 语句、优化 join 语句等等。 3、缓存技术 ...
  • TDK是什么意思,TDK怎么?SEO中的TDK分别代表标题,关键词,描述,那么对于TDK如何能提高网站关键词排名呢?一个好的TDK充分证明该...下面yetaoaiueo跟大家说说SEO中的TDK是什么意思,怎么利于SEO优化?   ...
  • --------finish, 3.984 s
  • 快读快:读入输出优化

    千次阅读 2018-08-26 20:28:23
    引入 初学OIOIOI的时候,只用的cin/coutcin/coutcin/cout,后来教练说,cincincin很慢,有的数组...再后来,发现有的题优化一下可以省很多时间,于是就学了快读快,(虽然自己不经常用,也很少手打……) 快读 ...
  • sql优化的几种方式

    万次阅读 多人点赞 2018-11-05 10:20:46
    一、为什么要对SQL进行优化 我们开发项目上线初期,由于业务数据量相对较少,一些SQL的执行效率对程序运行效率的影响不太明显,而开发和运维人员也无法判断SQL对程序的运行效率有多大,故很少针对SQL进行专门的优化...
  • Java 代码优化 Java 如何好 一个 for 循环

    千次阅读 多人点赞 2019-05-30 18:40:35
    一个简单的for循环,我学Java这么多年,我能不会吗!!!!开玩笑,哼。 我觉得我看这个文章,就是在摩擦我的智商。。。 。。。。。。。 看下面的两个图,for循环的区别在哪。 估计,一眼就看出来了: ...
  • Android之GPU过度绘制与图形渲染优化写在前面的话本文主要对过度绘制和图形渲染做一个概念性的描述,和简单的优化措施。 如果你已对过度绘制有过一些了解,那么你应该明白,仅是简单的层级优化对过度绘制的改善是很...
  • 关于NoSQL的思考:为什么我们要优化存储的性能
  • mysql数据库,其中有一张表数据量有3千万,多读少,如何优化? 我对表进行大量操作的时候,整个系统都无法访问了,请问是什么原因? 是因为对表执行大量的新增操作,IO变慢了?
  • 数学优化入门:凸优化

    万次阅读 多人点赞 2016-10-18 11:10:50
    做科研时,曾花了段时间学习凸优化,后来发现ML中其应用也非常普遍,想来今后可能还会接触,干脆做个系统的总结,方便以后查询。 博文内容主要参考Boyd(Stanford)的Convex Optimization,配套的slides,以及部分...
  • MySQL优化技巧

    万次阅读 多人点赞 2017-09-10 14:14:00
    MySQL优化三大方向① 优化MySQL所在服务器内核(此优化一般由运维人员完成)。② 对MySQL配置参数进行优化(my.cnf)此优化需要进行压力测试来进行参数调整。③ 对SQL语句以及表优化。MySQL参数优化1:MySQL 默认的最大...
  • mysql 磁盘读写的I/O优化

    千次阅读 2017-06-13 15:26:10
    #在 MySQL 5.1.x #版本中曾使用参数innodb_file_io_threads,指负责处理数据页上读写IO请求的后台线程数量。 #在 MySQL 5.5.x #中拆成2个参数:innodb_read_io_threads,...#如果系统读>,可以设置innodb_read_io_th
  • (2)试出查询优化的关系代数表达式。 (1)πCNAME,TEACHER(σSEX=女(SSCC)) (2)优化为:πCNAME,TEACHER(CπC#(πS#,C#(SC)πS#(σSEX=女(S)))) (基本思路:尽量提前做选择操作;在每个操作后,应做
  • 写入时复制(英语:Copy-on-write,简称COW)是一种计算机程序设计领域的优化策略。其核心思想是,如果有多个调用者(callers)同时请求相同资源(如内存或磁盘上的数据存储),他们会共同获取相同的指针指向相同的...
  • 执行计划是数据库根据SQL语句和相关表的统计信息作出的一个查询方案,这个方案是由查询优化器自动分析产生的,比如一条SQL语句如果用来从一个 10万条记录的表中查1条记录,那查询优化器会选择“索引查找”方式,如果...
  • SQL优化最干货总结 - MySQL(2020最新版)

    万次阅读 多人点赞 2020-06-29 16:55:47
    MySQL - SQL优化干货总结(吐血版),别辜负了自己的梦想,欢迎白嫖、点赞、收藏。
  • 下面是本文总结的第二部分内容:表操作相关的优化方法。 2. 表操作 2.1 多HTable并发 创建多个HTable客户端用于操作,提高数据的吞吐量,一个例子: static final Configuration conf = H
  • MYSQL优化大法1. SQL优化1.1 查询SQL执行频率1.2 定位低效率执行SQL1.3 explain分析执行计划1.3.1 explain之ID1.3.2 explain之select_type1.3.3 explain之select_table1.3.4 explain之type1.3.5 explain之key1.3.6 ...
  • 数据库优化 - 实例优化

    千次阅读 2019-10-25 10:30:00
    从网上去搜数据库优化基本都是从SQL层次进行优化的,很少有提及到数据库本身的实例优化。就算有也都是基于某个特定数据库的实例优化,本文涵盖目前市面上所有主流数据库的实例优化(Oralce、MySQL、POSTGRES、达梦)...
  • 因此在开发系统的时候,表结构设计是否合理,sql语句是否标准,出的sql性能是否优化往往会成为公司衡量程序员技术水平的标准。 我们程序员不是dba,不需要时刻关注sql运行时间,想方设法优化表结构,存储空间,...
  • 优化第四章凸优化问题 4.2凸优化

    千次阅读 2019-01-21 21:15:50
    也可以成 重要性质:凸优化问题的可行集也是凸集。 证明:可行集是满足不等式约束和等式约束的点的集合,首先不等式约束函数是凸函数,满足不等式约束的x,相当于是的0-下水平集,凸函数的下水平...
  • 在使用hbase过程中发现在写入hbase的数据量很大时,...下面将记录hbase写优化的过程。 1.禁止Major Compaction 在hbase进行Major Compaction时,该region将合并所有的storefile,因此整个region都不可读,所有对
  • Android性能优化系列之App启动优化

    万次阅读 多人点赞 2017-02-22 00:23:29
    Android性能优化系列之布局优化Android性能优化系列之内存优化Android性能优化系列之apk瘦身应用的启动速度缓慢是我们在开发过程中经常会遇到的问题,比如启动缓慢导致的黑屏,白屏问题,本篇博客就将介绍App启动...
  • Unity性能优化(三)-图形渲染优化

    千次阅读 2018-05-22 11:08:12
    这里有一篇得很好的文章,请看这个: 【Unity技巧】Unity中的优化技术 Unity性能优化-图形渲染优化 渲染流程简介 渲染问题的类型 处理CPU Bound 使用图形作业(Graphics Jobs)功能 减少向GPU发送的数据量...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,299,423
精华内容 519,769
关键字:

优化怎么写