什么更有效 - 将日志存储在SQL数据库或文件中?

时间:2011-08-31 13:00:45

标签: php mysql logging append fwrite

我经常用cron加载很少的脚本。现在我不存储任何日志,所以如果任何脚本无法加载,我会看到结果之前不会知道它 - 即使我注意到结果不正确,我也做不了什么,因为我不知道知道哪个脚本失败了。

我决定存储日志,但我仍然不确定如何操作。所以,我的问题是 - 什么更有效 - 将日志存储在sql数据库或文件中?

我可以在我的mysql数据库中创建'logs'表并将每个日志存储在单独的行中,或者我可以使用php的file_put_contents或fopen / fwrite将日志存储在单独的文件中。

我的脚本在工作时每分钟大约会增加5个日志(总计)。我做了很少的测试来确定什么更快--fopen / fwrite或mysql的插入。我将一个“插入”语句循环3000次以制作3000行并循环fopen / fwrite 3000次以制作带有示例文本的3000个文件。 Fwrite的执行速度比sql的插入快4-5倍。我做了第二个循环 - 我循环'select'语句并将其分配给字符串3000次 - 我还使用'fopen'打开了3000个文件并将结果分配给字符串。结果是一样的 - fopen / fwrite完成任务的速度提高了4-5倍。

那么,对于所有有经验的程序员 - 您在存储日志方面的经验是什么?有什么建议吗?

// 04.09.2011编辑 - 谢谢大家的答案,他们帮助了很多。每个帖子都很有价值,所以很难接受一个答案; - )

9 个答案:

答案 0 :(得分:12)

使用文件的日志效率更高,但存储在数据库中的日志更容易阅读,甚至远程(例如,如果需要,您可以编写Web前端)。

但是请注意,在数据库中连接和插入行是容易出错的(数据库服务器关闭,密码错误,资源不足)所以如果您决定使用数据库,那么您将在哪里记录这些错误?

答案 1 :(得分:6)

您可以使用Zend_Log等组件,它本身支持附加到同一日志实例的编写器概念。通过这种方式,您可以将相同的消息记录到一个或多个不同的位置,而无需更改日志记录代码。您可以随时更改代码以替换日志系统或以简单的方式添加新系统。

对于您的问题,我认为如果您(开发人员)是唯一需要阅读日志消息的人,那么日志到文件会更简单,更合适。

如果您需要其他人需要在Web界面中读取日志,或者您需要能够搜索日志,请转到db。正如其他人已经指出并发问题一样,如果你有很多用户登录到db可以更好地扩展。

最后,每分钟5条消息的日志频率几乎不需要为您的应用程序提供CPU,因此您无需担心性能问题。在你的情况下,我会从日志文件开始,然后在必要条件发生变化时更改(或添加更多编写器)。

答案 2 :(得分:6)

评论你的发现。

关于写入文件你可能是对的。
关于阅读你是错的。

写入数据库:

  1. MyISAM将整个表锁定在插入上,导致锁争用。使用InnoDB,它具有行锁定功能。
  2. 与1.相反如果您想对日志进行全文搜索。使用MyISAM,它支持全文索引。
  3. 如果你想要非常快,可以使用memory引擎,这会将表写入RAM。当CPU负载较低时,将数据传输到基于磁盘的表。
  4. 从数据库中读取

    这是数据库真正闪耀的地方 您可以将来自不同条目的各种信息组合起来,比平面文件中的更快更容易。

    SELECT logdate, username, action FROM log WHERE userid = '1' /*root*/ AND error = 10;
    

    如果在where子句中使用的字段上有索引,结果几乎会立即返回,请尝试在平面文件上执行此操作。

    SELECT username, count(*) as error_count 
    FROM log 
    WHERE error <> 0 
    GROUP BY user_id WITH ROLLUP
    

    不要紧,表格没有标准化,这对于平面文件来说要慢得多,而且难度更大。
    真的没脑子。

答案 3 :(得分:2)

速度不是万能的。是的,写入文件的速度更快,但如果它们位于数据库中,您可以更快地找到日志中所需的内容。几年前,我将CMS从基于文件的日志转换为Mysql表。表更好。

答案 4 :(得分:1)

编写文件系统应该总是更快。

然而,你应该担心。执行简单插入和写入文件系统都是快速操作。您需要担心的是当数据库出现故障时会发生什么。我个人喜欢写两个,所以如果出现任何问题,总会有一个日志,但你也可以从数据库中轻松搜索。

答案 5 :(得分:1)

这取决于日志的大小和并发级别。由于最新的,您的测试完全无效 - 如果站点上有100个用户,并且您可以说10个线程写入同一个文件,那么fwrite将不会那么快。 RDBMS提供的一个功能是并发控制。

这取决于您要执行的分析要求和批次。只是阅读记录很容易,但是如何在定义的时间段内汇总一些数据。

大型网站使用Scribe等系统来编写日志。

如果你说的是每分钟5个记录,那么这实际上是低负荷,所以主要问题是你将如何阅读它们。如果文件适合您的需要,请使用该文件。通常,仅附加写入(通常用于日志)非常快。

答案 6 :(得分:1)

我认为将日志存储在数据库中并不是一个好主意。通过文件将日志存储到数据库的优点是,您可以使用SQL的强大功能更轻松地分析日志,但是,您需要花费更多的时间来维护数据库。您最好设置一个单独的数据库服务器来存储您的日志,否则您可能会获得太多的日志INSERT,这将使您的数据库性能降低到生产使用;此外,与文件(logrotate等)相比,迁移,归档数据库中的日志并不容易。

现在你应该使用一些特殊的功能丰富的日志系统来处理你的日志,例如,logstash(http://logstash.net/)有日志收集器,过滤器,它可以存储外部系统中的日志,例如elasticsearch,结合一个美丽的前端,用于可视化和分析您的日志。

价:

答案 7 :(得分:0)

错误记录最好仅限于我认为的文件,因为如果数据库出现问题,您仍然可以记录。显然,如果您的错误记录需要连接到数据库,那么这不是一个选项!

然而,我还要说的是,一般日志记录是我在数据库中留下的内容,但这仅适用于您为审计跟踪等进行大量日志记录的情况。

答案 8 :(得分:0)

就个人而言,我更喜欢日志文件,因此我创建了两个函数:

<?php
function logMessage($message=null, $filename=null)
{
    if (!is_null($filename))
    {
        $logMsg=date('Y/m/d H:i:s').": $message\n";
        error_log($logMsg, 3, $filename);
    }
}

function logError($message=null, $filename=null)
{
    if (!is_null($message))
    {
        logMessage("***ERROR*** {$message}", $filename);
    }
}
?>

我定义了一个或两个常量(我使用ACTIVITY_LOG和ERROR_LOG都设置为同一个文件,因此您不需要并排引用两个文件以获得正在运行的整体视图)并根据需要调用。我还创建了一个专用文件夹(/ var / log / phplogs),我编写的每个应用程序都有自己的日志文件。最后,我转动日志,以便我有一些历史记录可以回顾客户。

自由使用上述功能意味着我可以非常轻松地跟踪应用程序的执行情况。