工作总结概述

本文档主要从我工作中涉及的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过滤列 



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值