对于一个新闻发布系统,一篇新闻的正文储存有很多种方式,最常见的就是随着标题等信息储存在关系型数据库中,如mysql;另一种方案是使用nosql存储,如mongodb;还有一种简单粗暴的办法就是直接吧文章正文存入一文件的形式存进磁盘。

本文主要测试mongodb和直接存文件的性能。
大约有5万篇文章,平均大小约为50kb。
测试机 Ubuntu 14.04 8核8G内存,5400RPM机械硬盘

测试过程也简单粗暴,随机读取1万个记录,然后输出文章长度,最后计算运行时间。
使用python和php两种语言进行测试。
mongodb的集合带有索引。

python版

import time
import random
import pymongo

print 'filedatabase ...'
start = time.time();
for i in range(10000):
    id = random.randint(0,50000)

    filename = "article/infotext/%d/%d.html" % (id % 100, id)
    try:
        fp = open(filename)
        content = fp.read()
        print len(content),
    except:
        pass
end = time.time();

print "filedatabase\n", end-start


print 'mongo ...'

start = time.time();
for i in range(10000):
    id = random.randint(0,50000)

    client = pymongo.MongoClient("localhost", 27017)
    db = client.files
    doc = db.article.find_one({'_id': id})
    if doc:
        print len(doc['content']),

end = time.time();

print "mongo\n", end-start

php版

<?php 

print "filedatabase ...\n";
$start = microtime(true);
for ($i=0; $i<10000; $i++)
{
    $id = rand(0,50000);

    $filename = sprintf("xjh/infotext/%d/%d.html", $id % 100, $id);
    $content = @file_get_contents($filename);
    print strlen($content).' ';
}

$end = microtime(true);

print "filedatabase\n". ($end-$start) . "\n";

print "mongo ...\n";

$start = microtime(true);
for ($i=0; $i<10000; $i++)
{
    $id = rand(0,50000);

    $mongo = new MongoClient();
    $db = $mongo->files;
    $collection = $db->article;
    $cursor = $collection->findOne(array('_id'=>$id));
    print strlen($cursor['content']).' ';
}
$end = microtime(true);

print "mongo\n". ($end-$start) . "\n";

测试前压缩一下内存

echo 1 > /proc/sys/vm/drop_caches

下面是测试结果:

python

cf@cf-Ubuntu:~/tmp$ python filedatabasevsmongo.py 
filedatabase ...
filedatabase
34.4837019444
mongo ...
mongo
15.6313991547
cf@cf-Ubuntu:~/tmp$ python filedatabasevsmongo.py 
filedatabase ...
filedatabase
27.576843977
mongo ...
mongo
15.4162368774

php

cf@cf-Ubuntu:~/tmp$ php filedatavasevsmongo.php
filedatabase ...
filedatabase
35.346391916275
mongo ...
mongo
0.85509300231934
cf@cf-Ubuntu:~/tmp$ php filedatavasevsmongo.php
filedatabase ...
filedatabase
29.030472993851
mongo ...
mongo
0.83656191825867

对结果进行一定的分析
1运行同一个程序,第二次运行笔第一次运行,在直接读文件上有速度的提升,是因为操作系统会把常用文件缓存在内存中,再次读取时,不必在硬盘里读取。
2php和python在直接读文件方面速度相当python略快
3python的mongo读操作笔php对mongo的读操作要缓慢很多,对于这个现象,只能怀疑是pymongo这个库的效率问题了。
4当反复运行测试程序,基本上会把所有文件缓存进内存,到最后测试结果显示,mongo的性能不如直接读文件。

cf@cf-Ubuntu:~/tmp$ python filedatabasevsmongo.py 
filedatabase ...
filedatabase
0.186345100403
mongo ...
mongo
14.8158619404
cf@cf-Ubuntu:~/tmp$ php filedatavasevsmongo.php
filedatabase ...
filedatabase
0.15131092071533
mongo ...
mongo
0.85830688476562

本文未对并发性能进行测试……
EOF