本文档主要从我工作中涉及的4个方向(文件解析,数据库,R和Hadoop)入手。主要记录一些,别人不容易发现的问题。google能简单检索出解决方案的问题,我就不多累述,并没有太多意义。 ======================================================================================================================== 0.文件解析 最初工作就是文件解析,怎样提高它的解析速度是一个关键性问题。一般解析文件不正常的耗时都是循环内产生的。我通常从2个方面入手,一就是减少不必须要的循环次数,这个需要对不同的文件格式选择不同解析思路。二就是重点检查循环内的每行代码,发现是否有引起不正常的耗时。在工作中有多个实例可以印证。举2个例子。 其一,早期进行插值的时候,每个时间点插值需要1个多小时。问题主要就是在于循环内频繁调用R的接口,而R的接口相对来说很耗时。为了解决这个问题,就可以通过降低调用R接口的次数。比如,将100次的参数拼接成一个大的参数传递给R。这样可以很好的优化性能。通俗来讲就是每次java掉R的时候可能有很多环境需要准备,因为java和R交互有复杂的通讯过程需要初始化。假设这个过程每次需要1秒,而本来需要调用100次需要100秒,现在将100次的参数一起传递,就可以降低java和R交互过程的初始化次数至1次,很好的提高性能。 其二,直接观察如下代码。 public class T1 { //耗时2711ms public static void m1(){ for(long i=0;i<8888888888l;i++) { if(9==i){ } } } //耗时663921ms public static void m2(){ for(long i=0;i<8888888888l;i++) { if("9".equals(i+"")){ } } } public static void main(String[] args) { long time = System.currentTimeMillis(); m1(); //or m2() System.out.println(System.currentTimeMillis()-time); } } m1()和m2()2段代码表达的都是同一个意思,但是耗时相差近300倍。实测中"=="和"equals()"性能的差距并不大。问题出在【i+""】,因为【i+""】进行了类型转换,而类型转换进行了内存的申请和内存放入数据2个步骤,而内存的申请非常耗时,尤其它被循环了8888888888次,这种耗时就被成倍的放大了。所以解析中我们应该尽量避免不必要的类型转换。 ======================================================================================================================== 1.数据库 postgreSQL中,我们主要用到3个参数配置文件,其中pg_hba.conf用来访问权限控制,pg_ident.conf用来映射操作系统用户和数据库用户之间的关系,用的比较少。我结合工作中遇到的问题和自己的理解对postgresql.conf中的参数重点讲讲 tcp_keepalives_idle tcp_keepalives_interval tcp_keepalives_count 这组参数默认值是0,意思是使用操作系统的默认值。Linux操作系统的TCP默认值得是2个小时才询问客户端是否存在,最初pgadmin的使用工作中,经常会中断连接,原因就是pgadmin在一定的时间内得不到服务器的响应就会中断连接。调整这3个参数会使数据库尽量短的时间内主动去询问客户端是否存在,避免pgadmin的超时。这里的原理同ssh链接超时是一样的。 shared_buffers 是数据库的缓存大小,而linux中本身也有自己的文件系统缓存,数据库的底层就是文件系统。所以它的作用并没有那么大,一般可以尽量的大,或者尽量的小都是可以的。如果设置的不大不小反而不好,因为数据会在shared_buffers里面缓存一份,文件系统里面也缓存一份,从而造成内存的浪费。当然我们可以禁用文件系统缓存,那buffer就可以调的尽可能大。 temp_buffers 数据汇总的时候有时候会将查询结果放入临时表中加快性能。而这时候应该让临时表尽可能的大,这样数据可以保证是存放在内存中,而不会序列化到硬盘上。 work_mem 这个参数通常在SQL语句中的order by、distinct和join连接上会使用到。如果你一条SQL语句,有多个以上的命令,可能会消耗多个work_mem的内存。如果处理大量数据,应该尽可能的一次性将数据加载入内存处理,但这样会造成max_connetion的最大数并发的时候很可能撑爆内存引发内核OOM机制。举个例子,如果work_mem大小1G,同时有100个链接,那么就是 100 connection X 1G = 100G,假若机器内存没有100G,会引发OOM问题。 checkpoint_segments --表示的是多少个WAL归档文件产生checkpoint。 checkpoint_timeout --表示多少时间产生一个checkpoint checkpoint_completion_target --表示checkpoint用多少百分比的时间把数据完整写入硬盘 checkpoint_warning --表示checkpoint时间小于这个值,系统会发生警告 通俗来说,例如我们做一个复杂运算,通常我们只关注结果,但是有时候运算到一半的时候触发了checkpoint(如时间太长,或者产生了太多的WAL日志),那么你现在必须停止运算,而将现在内存的结果写入到硬盘上。通常数据写入磁盘是很浪费时间的,是造成性能的下降的主要原因。这其实是我们不希望看到了,但是为什么数据库又有这个设置呢?我们简单比喻下,一条SQL语句可能运行总共需要2个小时,当运行到1个小时的时候,如果这时候你花5分钟把运算的中间数据存入硬盘,接着数据库崩溃。这时候,重启数据库后你可以从硬盘中读取存入的数据,继续完成剩下的1个小时的运算就可以了。否则断电内存数据消失,你需要从头开始运算。这个参数的选择是仁者见仁,智者见智的。通常我们可以调的比较大。因为数据库很少挂。 effective_cache_size 当查询的数据库表比较大的时候,有时候会发现不走索引,原因在于磁盘缓冲区的装不下那么多索引数据,造成了走索引的成本反而更高,所以提高这个参数大小,可以让索引更积极的被使用。例如,你查询出来的匹配数据可能有5个G,而你命中的索引的大小也可能有1个G。而这个时候cache已经容不下这么多索引了,为避免这种情况也就不会走索引。 max_locks_per_transaction 这个参数控制着每个事务能够得到锁的个数,在我们做分表的时候,一个主表下面,可能有几百上千张子表。访问每个表都会给它加一个锁,所以这个参数必须足够大。不然会有异常发生。 log_destination = 'csvlog' --csv模式输出 logging_collector = on --收集日志打开 log_directory = 'pg_log' --输出日期的陌路 log_filename = 'postgresql-%u.log' --输出的文件名加星期格式 log_truncate_on_rotation = on --可以覆盖文件而不是追加 log_rotation_age = 1d --一天生成一个日志文件 log_rotation_size = 0 --0为关闭按大小生成文件 log_statement = 'ddl' --只记录所有ddl语句 log_min_duration_statement = 2000 --记录所有运行超过2秒的语句 以上是我一般设置的日志配置项,可以很方便的在语句出错的时候进行调试,或者对性能堪忧的SQL进行优化。 总结一下,大多数数据库的参数默认值足够使用,不需要修改,我列出的一般都是遇到问题后调整过的。 讲讲数据库的备份,直接举例子 pg_dump postgres -- 备份postgres库输出内容到屏幕 pg_dump postgres -f 1.sql -- -f参数表示输出到1.sql pg_dump postgres > 1.sql -- 使用shell ‘>’符号等效上面一行命令 由于没有指定备份方式,使用的是纯文本SQL脚本方式回复,需要使用psql,执行下面命令备份恢复 psql \i 1.sql --or psql -f 1.sql 通常使用 自定义模式备份恢复,执行 pg_dump -Fc postgres > 2.dump --备份 pg_restore -d postgres 2.dump --恢复 备份指定的表 pg_dump -Fc postgres -t 'public.*' -T 'log_*' > 3.dump --备份所有public.*的表,但是不包括public.log_开头的。 pg_restore -d postgres 3.dump --恢复 pg_dump -Fc postgres -T 'log_*' > 4.dump --备份所有数据,但是不包括public.log开头的表 pg_restore -d postgres 4.dump --恢复 恢复的时候会自动创建除了public以外的其它模式 pg_dump -Fc postgres -t '(public|t).*' -T 'log_*' > 5.dump --备份public.*和t.*所有表,.... pg_restore -d postgres 5.dump --恢复 tip:如果备份指定了-t 表示备份表,恢复的时候需要模式存在。 如果备份的时候使用了-n ,模式会被自动创建。 ======================================================================================================================== 2.hadoop ======================================================================================================================== 3.R 几个麻烦点,在于R如何调用Hbase。部分API的查找比较困难。下面给出一些rhbase示例 rows<-hb.scan.ex("kpinfo",filterstring="ValueFilter(=,'substring:17.7861')") #subtring只能等于 rows<-hb.scan.ex("kpinfo",filterstring="PrefixFilter('12544_')") ##前缀小区 rows<-hb.scan.ex("kpinfo",filterstring="PrefixFilter('12544_') AND QualifierFilter(=,'substring:HSDPA_Users')") ##前缀kpi过滤 rows<-hb.scan.ex("kpinfo",filterstring="PrefixFilter('12544_') AND QualifierFilter(=,'substring:HSDPA_Users') AND ValueFilter(=,'substring:17.7861') ") ##前缀kpi过滤 值域 rows<-hb.scan.ex("kpinfo",colspec="h:HSDPA_Users",filterstring="PrefixFilter('12544_')" ) ##colspe过滤列
工作总结概述
最新推荐文章于 2019-12-11 09:36:41 发布