通过PHP登录到文件或登录MySQL数据库 - 哪个更快?

时间:2008-10-08 16:59:44

标签: php mysql

我有一个数据库驱动的网站,大约有50,000页。

我想跟踪每个网页/记录点击。 我将通过创建日志,然后每天批量处理日志一次来完成此操作。 我并不关心如何以最快的方式记录批处理过程。

你会如何记录,你认为哪个更快:

a)使用PHP附加到文本日志文件的末尾。

b)使用MySQL插入非索引日志表。

15 个答案:

答案 0 :(得分:17)

  1. 写入文件。旋转日志。

  2. 将文件批量加载到数据库 按计划进行。

  3. 选择这种架构有很多很多理由 - 易于扩展(写入许多日志,将它们加载到数据库),缺乏对数据库中SPOF的依赖(如果出现问题,你只需积累日志一段时间),能够在加载时进行清理和非平凡的解析,而不会给生产服务器带来负担,等等。

答案 1 :(得分:7)

您可以使用log4php尝试两种方式,它支持:

  • 通过xml和属性文件进行配置(与log4j结构相同)。
  • File,RollingFile,DailyFile,Echo,Console,Mail,PEAR :: Db,PHP错误,Syslog或NT事件和套接字appender。
  • 简单,TTCC,模式,Html和Xml布局。
  • 嵌套(NDC)和映射(MDC)诊断上下文。
  • 可切换的内部调试。

关于登录文件,您可以通过缓冲写入请求来提高性能。

答案 2 :(得分:6)

我会在MySQL中使用延迟插入。这样您就不必等待插入完成。

答案 3 :(得分:4)

使用数据库 - 这是唯一合理的选择。即使需要更长的时间。一旦你开始使用日志文件,那么你就会走上一条会让你痛苦的轨道 - 例如移动服务器,文件权限,排除负载平衡等......

如果您打开了数据库,那么我认为插入一行可能会更快。

然而,所有这些性能相关的唯一方法是确保编写一个简单的测试并测量它....

更新:我已经做了一个快速测试 - 果然如果你必须打开和关闭文件,它使用10,000行的测试速度相同或更慢:

然而,当您开始有多个进程执行此操作时,它会变慢,如下所示。这是10个并发进程(所有时间以秒为单位)

DB time: 2.1695
DB time: 2.3869
DB time: 2.4305
DB time: 2.5864
DB time: 2.7465
DB time: 3.0182
DB time: 3.1451
DB time: 3.3298
DB time: 3.4483
DB time: 3.7812
File open time: 0.1538
File open time: 0.5478
File open time: 0.7252
File open time: 3.0453
File open time: 4.2661
File open time: 4.4247
File open time: 4.5484
File open time: 4.6319
File open time: 4.6501
File open time: 4.6646
Open close file time: 11.3647
Open close file time: 12.2849
Open close file time: 18.4093
Open close file time: 18.4202
Open close file time: 21.2621
Open close file time: 22.7267
Open close file time: 23.4597
Open close file time: 25.6293
Open close file time: 26.1119
Open close file time: 29.1471

function debug($d)
{
    static $start_time = NULL;
    static $start_code_line = 0;

    if( $start_time === NULL )
    {
        $start_time = time() + microtime();
        $start_code_line = $code_line;
        return 0;
    }

    printf("$d time: %.4f\n", (time() + microtime() - $start_time));
    $fp = @fopen('dbg.txt','a');
    fprintf($fp,"$d time: %.4f\n", (time() + microtime() - $start_time));
    fclose($fp);

    $start_time = time() + microtime();
    $start_code_line = $code_line;
}

function tfile()
{
    $fp = @fopen('t1.txt','a');
    for ($i=0;$i<10000;$i++)
    {
        $txt = $i."How would you log, which do you think is quicker:How would you log, which do you think is quicker:";
        fwrite($fp,$txt);
    }
    fclose($fp);
}
function tfile_openclose()
{
    for ($i=0;$i<10000;$i++)
    {
        $fp = @fopen('t1.txt','a');
        $txt = $i."How would you log, which do you think is quicker:How would you log, which do you think is quicker:";
        fwrite($fp,$txt);
        fclose($fp);
    }
}

function tdb()
{
    $db = mysql_connect('localhost','tremweb','zzxxcc');

    $select_db = mysql_select_db('scratch');

    if (!$select_db) 
        die('Error selecting database.');

    for ($i=0;$i<10000;$i++)
    {
        $txt = $i."How would you log, which do you think is quicker:How would you log, which do you think is quicker:";
        mysql_query("INSERT INTO tlog values('".$txt."')");
    }
}

debug("");

tfile();
debug("File open");

tfile_openclose();
debug("Open close file");

tdb();
debug("DB");

答案 4 :(得分:2)

我相信平面文件的写入速度会更快。

答案 5 :(得分:2)

您应该尝试SQLite。它将为您提供写入文件的速度以及数据库的强大功能。

答案 6 :(得分:2)

几年前,我在C ++ Users Journal中读到了一篇关于loggin性能的文章。无论您使用数据库还是文件,最好的办法是编写未格式化的数据,这些数据可以在需要查看日志时(并且更有可能)“膨胀”为有意义的数据。记录的绝大部分成本都会记录写入目标的字符串,并且大部分时间都会浪费成本 - 从不读取日志。

如果它对您有用,我可以挖掘文章参考。

答案 7 :(得分:2)

如果您使用的是基于文件的日志记录或基于数据库的日志记录,那么您最大的性能影响将是文件/表锁定。基本上,如果客户端A和客户端B在相对较小的时间范围内连接,则客户端B将等待锁定在命令文件/表上释放,然后继续。

基于文件的机制存在的问题是文件锁定对于确保您的命中不会被破坏至关重要。唯一的方法是实现一个队列来对文件进行延迟写入。

使用数据库日志记录,您至少可以执行以下操作[使用MyISAM的MySQL]:

INSERT DELAYED INTO `hits` ...

有关详细信息,请参阅12.2.5.2. INSERT DELAYED Syntax

答案 8 :(得分:1)

我建议您使用一些测试用例进行测试。

我认为平面文件会更快,b / c这就是数据库正在做的事情 - 它只是将它写入文件。我能想到的唯一优势是,如果数据库可以同时运行,您可能会获得更好的结果。

答案 9 :(得分:1)

我做过类似的事情。我将每个记录记录到一个单独的文件中,然后我有一个抓取文件的批处理程序,将它们放入tar文件并将它们上传到中央日志服务器(在我的例子中,S3 :))。

我为每个日志条目生成随机文件名。我这样做是为了避免锁定文件进行轮换。以这种方式存档/删除非常容易。

我使用json作为我的日志格式,而不是典型的空白分隔日志文件。这使得以后更容易解析和添加字段。这也意味着我为每个文件编写一个条目比为每个文件附加多个记录更容易。

我还使用log4php + syslog-ng实时集中日志记录。我有log4php日志到syslog,然后转发到我的中央服务器的日志。这对较大的集群非常有用。需要注意的是,syslog消息存在长度限制,因此您可能会有更长的消息被截断。

答案 10 :(得分:0)

进入文件会更快,但进入DB会更好。

答案 11 :(得分:0)

全部取决于您的基础设施和限制。如果磁盘很慢,写入速度会很慢。如果SQL服务器滞后于请求,则插入将很慢。平面文件可能是最好的方法,但我会编写您的代码或使用现有代码(PEAR :: Log),以便您可以随意更改提供程序和存储方法。

答案 12 :(得分:0)

一些注意事项:

  1. 您认为您是否想要将日志数据与数据库中的其他数据相结合?如果是这样,db插入的开销可能是合理的,因此可以轻松利用现有的关系。
  2. 记录数据库中的数据是否可以减少您大量记录的数据量(由于数据库中的现有关系)?例如,用户活动数据库中的日志可以只是包含用户标识,活动标识和时间戳的表。这个精简在文件中的日志文件不是人类可读的。根据您的需要,您需要至少捕获日志文件中的一些用户数据,以确保它本身具有实用性和可读性。
  3. 您是否有机会在前端或通过管理工具利用此日志数据?如果是这样,DB写入可能更可取。

答案 13 :(得分:0)

正如其他人所说 - 它取决于很多东西,比如流量,磁盘速度等。你必须测试这两种情况。

在测试MySQL时,请尝试MyISAM和INNODB。从理论上讲,Innodb会因行级锁定而表现更好。

答案 14 :(得分:0)

如果这是针对数据库驱动的网站,为什么不只是使用Apache或IIS的内置日志记录功能,以及合适的报告工具,例如AWStats及其后,总是{{3 }}

AWStats和webserver日志记录是我的首选 - 你基本上是免费获得它 - 即使你没有进行流量分析,你仍然可以考虑自己解析Apache访问日志文件,无论你需要做什么批处理。 / p>