Loading...

Tag Archive for 'mysql'

    AD: 猛买 | 快递查询 | Jobsdigg | 很棒的男装店

Rails中压缩存储文本数据

继续压缩话题。之前写了 Rails生成压缩的静态缓存,以及配置nginx以支持直接发送压缩文件两篇文章。今天谈的是在Rails中,将大段文本内容以压缩格式存在数据库。这也是从公司的一个项目中获得的灵感。 原始需求 手头有一个结构简单的文本库,可以看做是key=>value。约180万条数据,2.8G(确实不算大,见笑了)。 这个库查询频繁,CPU在IOWAIT耗时颇多。 Linode服务器硬盘紧张,而CPU富裕。 若能通过压缩减小体积,备份/回导时也会更省时。 实施过程 整个实施过程做到了无缝转换,不需要停服务。 第一步:将文本字段类型由TEXT修改为BLOB;新增一个is_gzip字段用于标识是否经过压缩,默认为0。 * 需要注意,BLOB和TEXT最长支持65535字节。 第二步,修改Rails相应的Model。代码示例(压缩content字段): class TextData < ActiveRecord::Model def content if self.is_gzip Zlib::Inflate.inflate(super) else super end end def content=(info_content) super Zlib::Deflate.deflate(info_content, 9) self.is_gzip = true end end 再一次感叹super的便捷。修改代码后,需要重新部署一下Rails应用。 第三步,创建一个rake任务,用来批量做转换。关键部位只消这么做: text_data.content = text_data.content text_data.save 第四步,在做过修改的表上做一次optimize table,以释放那些不需要的空间。 效果观察 经如上处理,2.8G数据只剩1.4G。如果用了Gzip而不用Deflate,有可能更小。 IOWAIT未见明显下降。压缩前,单条记录理论上可以通过一次IO完成。 备份的速度确实有所提升,意料之中。 更多信息 这种思路同样适用于PHP、Python以及其他语言下的Web应用,只是在Rails中搞起来更为轻松。 Mysql提供了Compress/Uncompress两个函数,但是不建议直接使用。一方面会增加数据库服务器计算的压力;另一方面,如果用了主从,每个服务器都得算一次。 Zlib::Deflate.deflate 的第二个参数是压缩的level。我用随机数据测试,Level 9压缩后的体积比Level 1 [...]

脚本分享:备份数据库到Amazon S3

家里网络不好,备份服务器上几G的数据并下载回来极其痛苦(这还是压缩过的)。于是我想把数据备份上传到AmazonS3上,一来Linode到Amazon网速应该不是问题;二来,“Cloud Storage”也要比我的笔记本硬盘更靠得住。 科普一下: S3 = Simple Storage Service。是由Amazon提供的在线存储服务。 我使用了ruby下的s3sync作为与Amazon交互的客户端,并写了一个shell脚本对它进行了简单包装。脚本用法很简单: ./backup_mysql_and_sync_s3.sh dbname1 [ dbname2 ...] 只要在参数中指明数据库名,就会自动将数据库内容用mysqldump导出并压缩,然后上传到S3中。下面详述一下脚本的获取和配置,搞定之后备份东西很轻松。 0. 环境依赖 依赖于ruby。Dreamhost上面自己有ruby,如果在用Linode而且是Debian系列,可以apt-get install ruby装上。 需要有Amazon AWS账号。脚本需要使用AWS_ACCESS_KEY_ID/AWS_SECRET_ACCESS_KEY进行身份验证。 1. 获得s3sync-s3cmd,创建bucket svn checkout \ http://s3sync-s3cmd.googlecode.com/svn/trunk/ \ s3sync-s3cmd cd s3sync-s3cmd/s3sync export AWS_ACCESS_KEY_ID=”your_access_key_id” export AWS_SECRET_ACCESS_KEY=”your_serect_access_key” ruby s3cmd.rb createbucket bucket_name 如果一切正常,创建操作不会有任何返回。出错时会有相应提示。 此处需记下s3cmd.rb的位置、以及创建的bucket_name,备用。 2. 获得shell脚本,修改配置 脚本地址在此处,可以直接用下方shell脚本获得并解压。 wget http://www.blogkid.net/wp-content/uploads\ /2010/02/backup_mysql_and_sync_s3.zip unzip backup_mysql_and_sync_s3.zip chmod +x backup_mysql_and_sync_s3.sh 打开backup_mysql_and_sync_s3.sh。修改下方这些配置: export [...]

Mysql笔记两则

1、BLOB字段最长只能存65535个字节。 之前一直以为BLOB字段是不限长度的,犯了经验主义的错误。直到使用中遇到了问题,一翻文档,原来最多只能存65535个字节呐。 如果想存更多,可以用MediumBLOB或是LongBLOB。当然,过多使用BLOB字段不是个好习惯。 对于TEXT类型的字段,也有一样的限制。如果想要存放更多内容,可以用MediumTEXT或LongTEXT。 2、在不同事务中Update同一条数据,mysql会保证串行执行。 即便不先使用select xxx for update锁住这条记录,mysql依然会保证不同事务中对同一行数据的update,串行地执行。举例来说,假设有两个事务T1、T2。在T1中先执行 UPDATE table_name set field_A = ‘xxx’ where id = 123 可以顺利完成。然后在T2中update同一条记录: UPDATE table_name set field_A = ‘yyy’ where id = 123 此时就会阻塞,除非T1中做了提交(commit)或回滚(rollback),不然无法执行完成,有可能超时返回。也就是说,mysql为事务中的update操作自动加了锁。 这个特性有什么用?可以在update时,安全地使用 A=A+1 之类的赋值语句,而不必担心没有先锁定记录而将数据改脏。 推而广之,其他数据库会怎么做呢?若有兴趣,可以装一个PGSQL尝试下。 感觉开发中遇到的很多问题,想明白了都很简单。但只有动手试试、查查资料,才能真正验证想法。

一次MYSQL优化

还是我做的淘宝随机商品的玩意,现在有大约30万的数据,用MyISAM表存放。随机推荐商品我一个随机的查询来实现,原来的语句是这样的: select * from goods where id >=  (ceil  ( select max (id) from goods ) )  limit 1 因为id是主键,上面有索引,所以执行起来挺快。但我发现需要增加一个字段用来标识那些不适合推荐出来的商品,比如很多丰胸的减肥的,于是就增加了一个hide字段。这个字段我建了索引,但可能的值只有0和1,大家也知道,在这上面建索引意义不大。相应地,SQL语句改为: select * from goods where id >= (ceil ( select max(id) from goods where hide=0 ) ) and hide = 0 limit 1 在我的服务器上,上面的语句跑一次大概需要1.4秒。这很难接受,于是考虑做优化。 此处我联想到看过的一些文档:在Innodb中,Secondary Index的所有Leaf Nodes上面同时包含了所指向数据记录的主键信息,而不是直接指向数据记录的位置信息;而在MyISAM表中正好相反。上面的查询语句,子查询正是要用到主键的信息,于是我考虑把hide 和主键 id做联合索引。索引生成以后,先用explain查看一下: 发现其中的“Subquery”已经显示“Select tables optimized away”。尝试查询(为了显示出来干净,仅查询了id和title两个字段): 时间是0.00秒,比起优化之前,降低了两个数量级。改为联合索引起到最大的作用是让中间的子查询不需要去表中查找信息返回最大的id值,而直接可以从索引中得出。 这个故事告诉我们,MySQL里建立索引应该考虑数据库引擎的类型。我自问对Mysql还不够了解,持续学习中。

Mysql中Union的子句不支持order by

我对DB知之甚少,这问题只在Mysql遇到,不知道别的DBMS是不是也如此。 问题是这样的,我打算在一个表里获得与某一行记录相邻的两行,并且想通过union一起取出来,所以这么写: select id,title from subjects where id>#some_id# order by id limit 1 union select id,title from subjects where id<#some_id# order by id limit 1 但出现了错误提示“Incorrect usage of UNION and ORDER BY”。看来不能这么用union和order by,但这里确实是需要order by的。很快,我想到了一个变通的写法: select * from ( select id,title from subjects where id>#some_id# order by id limit 1 ) union select id,title from subjects [...]

装了Appserv如何使用InnoDB

今天有点空,想到实战一下在windows上部署个简单的rails程序。最后其他都搞好了,可是在运行数据迁移脚本的时候,提示mysql不支持innodb,没法子建表。都是因为当初图省事用appserv一下就装好了AMP,几个组件都几乎是最小安装。后来用apache配置FastCGI的PHP时就费了些周折。 最后找到了Mysql的配置文件my.ini(在mysql的安装目录下),搜索innodb,到了一行写着skip_innodb的地方。把这行用#号注释一下,重启mysql,就可以用innodb了。 做完还是觉得rails的嘴太刁,其实大部分时候,用MyISAM就够了吧。

干掉SimpleTagging (警惕copying to tmp table on disk)

SimpleTagging插件是我一直都在blog上用的tag插件,哪怕WP出来了内建的tag支持,我还是保留了SimpleTagging,因为它可以提供一个相关文章列表。为了这个相关文章,我每次写东西都会添加两次tag:一次是添加到wp自带的tag系统,一次是SimpleTagging。 但昨天发现服务器上mysql数据库进程的CPU占用经常有大的波动,忍不住用show processlist;看了一下。发现在CPU占用较高的时候,主要是涉及到SimpleTagging进行相似度比较的操作。由于我的文章太多、查询的语句也比较复杂,所以Mysql每次都会进行”copying to tmp table on disk”。可想而之,这样的操作有多耗资源。不过还是可以较快地处理完,所以在slowquerylog里没有这些查询。 但还是不能容忍每一次查询都来一个copying to tmp table on disk,权衡之下,只好干掉了SimpleTagging插件。这下不能显示相关文章了,但好处是不用每次写文章都加两次Tag了。Wordpress作为一个blog系统是非常好用,但插件往往会用得太多,一个页面要几十次查询的情况非常普遍。当文章的量比较大(我已经有一千几百篇文章),SimpleTagging需要在这么多文章中寻找相似条目,自然会慢下来。至于copying to tmp table on disk的出现,往往意味着还要进行file sort,在开发的时候,应该多用explain,看看能做哪些优化。

开源是一种精神

一个朋友昨天写了篇文章(在这里),其中提到了国内经常被提及的“抄袭”。碰巧这次去参加阿里的网络工程师大会,所参与的话题也都是开源方面的东西。所以想写这一篇文章谈谈自己的想法。 首先是谷歌抄酷讯这件事,明眼人一看就知道是这个小网站赶到了谷歌的压力,只能出此下策炒作自己。让我想起那时候电脑爱好者上头条登了一个很无耻的购物论坛的软文,里面把很多业内人士谈BuyRen论坛的部分都改成了描写他们自己网站的内容。炒作无罪,但是通过这些下三烂的手段,实在是让人鄙视的。 话说回来,今天我们聊的是开源。在网络工程师大会上,我听了PHP之父Rasmus的演讲,感触最深的是他说:“Even I started the project, I am a contributer. ”意思是说虽然他创造了PHP并开发了早期的版本,但他现在的身份也不过是这个项目的贡献者之一。他认为要让一个项目持久地发展下去,作为创始人,应该放弃对它的控制。 他自己说,“I am a tech guy.”在国外做技术的人和国内地位是不一样的。我所了解的在国内大家都羞于说自己是做技术的。一些长辈们也告诉我将来可以先写两年程序然后去公司的管理层XX。这彰显的是国内人们浮躁的心态。在Google就有一些资深的工程师,他们的待遇比副总裁还要高,他们不会涉足公司的管理,因为他们不适合做这个东西。但放到国内的话如果你35岁还在写程序恐怕在家里老婆也会看不起你。 还有一点就是国外人很有钱,所以一些NB的Geek可以从事自己喜欢的事情,然后通过Paypal会得到不少捐助。一些开源的项目也是这样,比如CakePHP。在国内大家一方面对技术并不重视,另一方面大部分人对在网上花钱还是比较害怕的。不过最近好像有了些起色,周曙光不算一个Geek,但是她的所作所为得到了很多人的认可,他现在的三星相机就是通过捐助获得的。 开源是一种精神。在开源社区诞生的一系列产品支撑起了整个互联网。比如Google,比如Yahoo,还有很多大大小小的网站,一群充满热情的人们持久地为开源项目贡献着力量,而并不谋取什么回报。我们看到了一个又一个优异的产品:PHP,Python,Mysql,Ubuntu… 昨天的沙龙由Alone谈了一下Ubuntu,以后的沙龙我们会加入更多开源方面的东西。Lupa社区该不该给我们些活动的经费呢,呵呵。 最后,要感谢Fenng大哥帮我要到了参加网络工程师大会的入场券。希望他工作不要太累,照顾好自己。

About V2Read

晓光说,V2Read又上不去了。都怪我一时激动,昨天速度恢复时,马上取消了对IP的限制。结果很快就又不行了。头大。 今天有朋友让我用他的服务器放V2Read的程序,可是服务器的Web服务是IIS的,想把V2Read跑在上面还需要费些周折——主要是Rewrite功能没有。而且数据抓取这一块跑在服务器上确实很耗费资源,不知道该怎么解决。 今天开会到很晚,一回来就跑到MT上看了一下Livid租的服务器。档次居中的那一款每年需要$1000,不是一笔小钱。在DH的Shared Server上慢下来的不是Apache,而是Mysql。 SIFE的Project已经要开始启动了 。我还是再给DH发一封信说明下情况吧。ProjectZLLP离完善还有距离,但是这是一个永远都不会完成的Project。 明天的沙龙,不知道效果如何。今天我希望Alone能就数据抓取这一块为主题做一个沙龙,他不愿意做。其实技术这种东西,参与交流的人少一点,大家都能钻得很深入。

如何解决Mysql中文全文索引

UPDATE:看到有很多朋友搜索mysql中文的全文索引到了这里,想和大家说,用mysql进行中文的全文索引是很难的。我已经找到了用Lucene解决的办法,不过在实际应用中选择了另一个全文检索工具“Sphinx”,我也写了一篇关于Sphinx和Rails协作的文章。请看看下面显示的相关文章里和Lucene有关的内容。左边推荐的这本书是一个详细的关于Lucene的教程。 V2Read是我第一个需要处理海量数据的Project,主要的数据是大量的图书信息。但是对于正在飞速增加的数据,我有点束手无策。现在在V2Read的搜索是使用Like进行简单的匹配,不用说,效率很差。所以现在的搜索只搜书名都很慢。 我下午花了一些时间来找Mysql在中文全文索引方面的内容,可是没找到什么有帮助的。大家提供的近似于Hack的方式倒是满有意思。比如说先进行分词,然后在中间插入空格,搜索的时候就能搜出来了;比如说先把内容转化成拼音(汗一个先),然后存进数据库——实在让我感叹群众的智慧就是伟大啊。 不过搜来搜去还是没有解决这个问题。全文索引难道真的就这么难?不知道Livid的V2EX是怎么做的。想到这里,突然有了去翻Babel程序的冲动,顺便也可以看看PW的源程序,肯定能找到蛛丝马迹的。 今天和zhanghe4聊天,说起V2Read。去年这个时候我在设计店评的时候,他给我看了dianping.com的个人主页,说最好提供这样一个东西。那时的我虽有满腔热情,到底没啥水平,看着那个伪静态的地址,猜测着那边高深莫测的技术,心里没底。但今天的V2Read全部都是伪静态链接,以前觉得那么NB的东西现在也看着稀松平常。很多时候自己都没有察觉,实际上成长了很多。 我正在做一个PPT,为我们新的沙龙做准备。但是在谈问题的深度上,实在不知道该怎么把握。深入到技术的细节,有一大堆内容,退到整体的设计,好像内容也不少,hoho。 不过这个中文全文索引实在是让人发愁啊。 UPDATE: 我去查了PW的程序(“search.php”) 以及Babel的程序,发现它们所使用的全是Like。有些失望。看来只能通过提升服务器性能来提高效率了。