2009年12月

我的2009

每每年末,总是有很多想法从四处冒出来,整个一年的最后一天了,总要留下一点什么东西。

回首过去的一年,发生了很多事,自己也变了…
离开了学校,离开了那种无牵无挂的生活,走上这个操蛋的却又让人期待的社会。
学会惦记那帮曾经朝夕相处的兄弟,会觉得天南海北的聚到一起,很好。
公司动荡,换了团队,又换了团队,终于还可以做一个喜欢的工作。
中国互联网发生了很多事,本来不政治的我,开始变得忧国忧民,变得愤青起来。

回首过去的一年,也有很多事一如既往,自己还是那样…
父母身体也还健康,他们一如既往的生活着,为我操着心。
我也还是那么理想主义的相信很多东西,期待着,追求着。
周围的兄弟们还是像以前一样,会叫我老高,会跟我说一些事。

总之过去的这个2009,值得记录的东西很多,值得回忆的也很多,姑且都放进记忆吧,在这个时候,我想,感谢一些人,再去期待一个美好的2010才好。

感谢父母,给我这么多的理解和支持,让我有足够的空间按照自己的想法去成长
感谢朋友,对我如此信任,给我强烈的存在感
感谢团队,让我不用去压抑什么,而可以做自己喜欢的事
2010,我会做我能做到最好的,去感谢你们,去回报你们。

期待2010。
有能力为父母做点事情,让他们开始感觉儿子长大了。
还可以为朋友做点事情,他们的信任是应该是正确的。
能给团队带来一些变化,团队给我了那么多,我要回报。

2010,我期待一个美好的2010,一切都会向着好的方向发展,一切都会越来越好!

如何写出高性能的MySQL查询

想写这样一篇文章很久了,但始终没有下手。最近帮同事看了几个查询,而且自己也在考虑一个索引系统的问题,所以今天就把这个写了。介绍一下MySQL的索引机制,还有一些MySQL查询的优化策略。鄙人才疏学浅,很可能说的不对,请路过的各位大侠批评指正,献丑了。

首先,说说MySQL的索引存储方式。MySQL的索引一般是B-Tree的结构存储的,内存表也有Hash索引,但是内存表的出镜率似乎已经低到了用“可怜”来形容的程度,所以我们只考虑B-Tree索引。
然后说说MySQL的联合索引。联合索引对于一个DBMS总是非常重要的,因为每一条SQL语句的条件子句是单条件的可能性很小,大多数情况下为组合条件,因此对于组合索引的依赖也就很强。MySQL对于联合索引的创建规则通过一个例子说明:
对于一个在列:col_a, col_b和col_c上的联合索引,MySQL会建立

index(col_a), index(col_a, col_b)和index(col_a, col_b, col_c)

这样三个索引。

介绍完一些基本原理,我们来看MySQL对于索引的选取规则和索引的建立原则(这些规则都是个人总结的,多来源于互联网,也有自己的经验)
对于单个索引,一般来说MySQL的查询优化器总能在若干查询条件中选取效率较高的一个使用,所以不必投入太多精力,一般来说查询容易出现的问题容易出现在联合索引。这里以一个两列的索引为例,说明一些问题。
例如:

idx_a_b (col_a, col_b)

建立做和索引的列进行or组合不可使用索引
例如:有条件

col_a = val_a or col_b = val_b

这个条件,是不可以使用idx_a_b索引的。然而同样的查询对于却可以使用这样的索引idx_a(col_a)或者idx_b(col_b)的,因此在建立索引的时候就要考虑到出镜率最高的条件是什么,建立怎样的索引。而如果同时存在idx_a和idx_b两个索引的话,MySQL也只会选择一个使用,尽可能使用索引把结果集缩小,再在这个结果集中遍历,使用其他条件筛选。
联合索引对非前缀列不生效
例如:条件col_b = val_b这个条件是不会使用这个索引的,因为索引idx_a_b的前缀列是col_a。因此在建索引的时候,就要注意到,是否有很多使用这种条件的查询,需要为col_b单独建立索引。
对于组合索引,遇到范围查询则放弃使用剩余部分
例如:条件

col_a = val_a and col_b = val_b

是可以使用整个索引,而对于

col_a between val_a_left and val_a_right and col_b = val_b

这个条件,只会使用索引的col_a这一部分,不会使用整个索引。对于这样的查询,我们有一个优化策略,若col_a是一个离散变量,则建议使用in代替between,例如,

col_a between 1 and 5 and col_b = val_b

建议写成

col_a in (1, 2, 3, 4, 5) and col_b = val_b

这样是可以使用整个idx_a_b的。

现在能想到的对于组合索引的使用就这些,还远远不够全面,不过了解了这些原理,一般的查询都是可以分析的。接下来介绍几个策略性的SQL优化。
尽量少的选择列数
选择你需要的列,不用图省事就直接写个select *,一来是为了减少通信的开销,再有就是如果你所选的列,都建立索引,那么这次查询就不会对表数据进行任何操作,只查索引,就返回。
减少count(*), group by, distinct这样的操作
这三种操作将进行大量的计算,对数据库服务器造成很大压力,而且很慢。这样的查询能避免就避免,能缓存就缓存。
对于limit offset,若offset值较大,则采用分割结果集策略
limit offset操作一般用于翻页,当offset值较小的时候直接使用limit offset效率搞,但当offset值增大到一定程度,这个查询效率就会骤然降低。建议在大offset的情况下,采取这个策略:缓存上一次结果的尾数据,在新的查询中不使用offset,直接根据缓存结果进行查询。
例如:

select * from tb limit 100 offset 500000;

offset值很大,建议这样做:缓存上一次结果的主键值id=id_val,sql改写为:

select * from tb where id>id_val order by id limit 100

这条sql的效率将比上一条高很多倍。

策略性的优化也姑且先想到了这么几条,很不全面。综合上面的这些查询优化策略,我们还有几个提高性能的系统配置和管理策略。例如:
定期重建索引
一张表用的时间久了,数据频繁更新,索引碎片会很多,降低查询效率,重建索引可以整理这些碎片,大大提高查询和写入的效率。
配置恰当的query_buffer
如果你的机器有足够大的内存,那多分给MySQL一点吧,在一台8G内存的机器上,我们一般会分给MySQL 4到6个G,query的缓存会给你带来惊喜的。
选择恰当的引擎
常用的MySQL引擎有Innodb和MyISAM,前者更稳定且支持行级锁,后者处理一般查询效率更高。二者各有特点,一般我们会使用主从策略,主Innodb,从MyISAM的做法。
在恰当的时候分表或分库
MySQL很强大,但对于200到300万以上的数据进行处理,性能就开始有明显的下降了,因此一般到这个数量级,就建议拆分数据了。
别让查询链接阻塞
MySQL可以配置连接的超时时间,这个时间如果做得太长,甚至到了10min,那么很可能发生这种情况,3000个链接都被占满而且sleep在哪,新链接进不来,导致无法正常服务。因此这个配置尽量配置一个符合逻辑的值,60s或者120s等等。

当下能想到的也就是这些~~略显肤浅,不过就写到这里吧,希望可以抛砖引玉,给大家一个优化MySQL的建议。

的确应该有几个明确的小目标

看了兄弟的签名,觉得的这小子的确挺NB的,而且的确应该有几个目标。
毕业半年了,经历了很多,公司飘摇不定,调整团队和工作,甚至几乎已经离开公司,真的很多。不过,想想这半年,似乎有些茫然。
所以接下来的一个Q应该有几个明确的目标,三个月的时间,刚刚好去完成一些东西。
我愿意称自己为程序员,而且乐于用代码说明一切。
在接下来的这个Q:
主要精力要放在Java上,因为对于Java,我需要转变一些东西,观念,态度。目标暂且定为,作为常规开发人员,完成一个平台级应用的开发工作,期望能对Java语言有所见解。
然后应该是Perl,才上手时间不长,我发现已经爱上这个语言了。目标定为,启动一个开源项目,发布第一个版本,并且推动项目发展,使用者至少要渗透到阿里系。
还有C,接下来要对之前的图片平台进行一次完善,至少让这个平台能承载整个公司所有业务对图片的需求,包括业务层的,也包括技术层面的。
接下来才是PHP,用了这么长时间,感情很深。对于LotusPHP这个项目,想进去,却始终都没开始。接下来的一个Q,至少为LotusPHP贡献4位数的代码吧。
Coding应该只有这些,对于Linux,想了很久的RHEL 5.x配置手册,始终都没有上手,如果还有时间,我想应该继续吧。
2010,我来了!

关于库与框架的思考

周六去参加了D2论坛,嘉宾都是大牛,Baidu的金大为,Tencent的甄焱鲲,去了Douban的克军,Taobao的明城,还有Koubei的秦歌。大家都讲了很多,有很前沿的技术,也有高屋建瓴的理念,但似乎都没有造成太大的振动。只是回来以后脑子里过这一整天听到的东西,对克军讲的从YUI的升级看前端演化有一些想法,对框架与库的概念。也不扯那些冠冕的东西,胡乱引用别人的东西了,就说说我对这两个东西的理解。
所谓库,一个应用的封装集合,旨在增强代码复用,简化开发者的工作。对于开发者,要做的只是找到一个适合自己的库,所谓适合就是说这个库能提供你所期望的输出,了解这个库所要求的输入规则。应用的时候,就把自己的数据按照约定组织,传给库,库将返回你期望的结果,则直接使用这个返回数据就OK了。
所以框架,是一种代码结构的约定和一些为了工程代码的框架代码,旨在让工程代码条理清晰,更易维护,可读性更强,更高的层次,安全性更高,扩展性更强等。对于开发者,适合与不适合之说,并不确切,而是有了很多主观因素,比如开发者对一个框架的代码结构设计是否同意等。使用一个框架,需要了解这个框架的约定和运行机制,然后依据这个框架的约定组织自己的代码。
不论是从存在的意义还是应用方式上,库和框架有非常明显的区别,但江湖上流传的各种框架,各种语言的似乎都对这两个概念稍有混淆,尤其是PHP框架,库和框架混淆比较严重,主流的那些框架,提供各种功能,数据验证器,认证码生成器等等,十分完整,十分强大。也包括我参与的KiwiPHP还有他的升级版lotusphp,都有这种现象。
我认为对于一个好的框架来说,或者用框架这个词并不准确,是框架和库的组合体,作为这样一个东西,要造福PHP开发者,应该把框架和库这两个部分清晰的拆分开,并提供一种有机的组合方式,实现方便的库订制服务,这样一来,所有的库都可以以插件的方式集成进来,扩展性可以大大提高,而且对于框架使用者只需订制自己需要的一些库,使用起来更加轻量,效率也更高。
刚词说道框架和库的组合体,想到一个词:平台,但又感觉平台这个词太大了,一个平台需要提供一项工作所需要的一切服务。针对开发来说,框架和库是远远不够的,还有包括测试工具,IDE等等很多东西。
以上就是我对框架和库的一点个人看法,之后的一段时间,我想我会试着做一些跟这个相关的事吧,有进展了再来回报。

身体是革命的本钱

今天身体终于顶不住,感冒了,像榆钱姐姐咨询的时候,偶然觅得如下一段话:
---------------- jiajun.org 官方分界线 开始 ----------------------
我们的身体一直默默无闻地支撑着我们。偶而实在支撑不住了,用一声咳嗽,一点点发烧,一个哈欠,一个寒占,甚至流一些鼻涕来提醒我们一下,我们却不允许有这样的反应。就按耐不住去药房的冲动,给它吃点抗生素,喝点药水,吃点药片,打个小针……
我们拼命糟蹋它,它却拼命地为我们辛苦工作。而我们不让它那怕发出一点儿反抗的声音
这个世界上还有比什么更爱你呢?我们的身体。还有谁比这更是你的好朋友呢?
我们的身体在我们吃下的东西中找一些尽可能有用的东西,来修复受损的细胞和组织,在我们有限的睡眠时间来给我们造血液,排除垃圾,全力以赴地为我们设身处地的服务。希望我们在明天醒来时能够精神一点,希望能够采集到一点身体需要的东西给它。
可是终于有一天,身体顶不住了,我们也生病了!
---------------- jiajun.org 官方分界线 结束 ----------------------
身体真的很重要,今天一整天混混沉沉,工作基本都给别人在做,自己看到代码都是混混沉沉的。晚上早早的回来睡一觉,哦弥陀佛,现在还好,脑子不晕了,可以翻翻代码。
对大家说:感觉身体吃不消的时候,稍微休息一下,古人说磨刀不误砍柴工,养足精神再回来工作!