簡體   English   中英

通過 PHP 登錄到文件或登錄到 MySQL 數據庫 - 哪個更快?

[英]Log to file via PHP or log to MySQL database - which is quicker?

我有一個數據庫驅動的網站,服務大約 50,000 頁。

我想跟蹤每個網頁/記錄命中。 我將通過創建日志來做到這一點,然后每天對日志進行一次批處理。 我不關心我將如何進行批處理,只關心最快的記錄方式。

您將如何登錄,您認為哪個更快:

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

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

  1. 寫入文件。 旋轉日志。

  2. 按計划將文件批量加載到數據庫中。

選擇這種架構的原因有很多——易於擴展(寫入許多日志,將它們加載到數據庫),不依賴數據庫中的 SPOF(如果出現問題,您只需積累一段時間的日志) ,在加載時進行清理和非平凡解析的能力,而不會增加生產服務器的負擔,等等。

您可以使用log4php嘗試兩種方式,它支持:

  • 通過xml和properties文件進行配置(結構與log4j相同)。
  • File、RollingFile、DailyFile、Echo、Console、Mail、PEAR::Db、PHP 錯誤、Syslog 或 NT 事件和套接字附加程序。
  • 簡單、TTCC、模式、Html 和 Xml 布局。
  • 嵌套 (NDC) 和映射 (MDC) 診斷上下文。
  • 可切換的內部調試。

關於登錄文件,您可以通過緩沖寫入請求來提高性能。

我會使用延遲插入到 MySQL 中。 這樣您就不必等待插入完成。

使用數據庫——這是唯一明智的選擇。 哪怕時間稍微長一點。 一旦你開始使用日志文件,那么你就會走上一條會給你帶來痛苦的軌道——例如移動服務器、文件權限、排除負載平衡等......

如果您打開了數據庫,那么我認為插入一行可能會更快。

然而,與所有這些性能相關的唯一方法是編寫一個簡單的測試並對其進行測量......

更新:我已經做了一個快速測試 - 如果你必須打開和關閉文件,使用 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");

我相信平面文件的寫入速度會更快。

你應該試試SQLite 它將為您提供寫入文件的速度以及數據庫的功能。

幾年前,我在 C++ 用戶雜志上讀過一篇關於登錄性能的文章。 無論您使用數據庫還是文件,最好的做法是在您需要查看日志時(更有可能)將未格式化的數據寫入有意義的數據。 日志記錄的絕大部分成本是為寫入目標的字符串提供信息,而大部分時間都浪費了這些成本 - 永遠不會讀取日志。

如果對您有用,我可以挖掘文章參考。

我建議你用幾個測試用例來測試兩者。

我認為平面文件會更快,b/c 這正是 DB 正在做的事情 - 它只是將它寫入文件。 我能想到的唯一優點是如果數據庫可以並發運行,你可能會得到更好的結果。

我做過類似的事情。 我將每條記錄記錄到一個單獨的文件中,然后我有一個批處理過程來抓取文件,將它們放入一個 tar 文件並將它們上傳到中央日志服務器(在我的情況下,S3 :))。

我為每個日志條目生成隨機文件名。 我這樣做是為了避免鎖定文件進行輪換。 以這種方式存檔/刪除真的很容易。

我使用 json 作為我的日志格式,而不是典型的以空格分隔的日志文件。 這使得將來更容易解析和添加字段。 這也意味着我為每個文件編寫一個條目比為每個文件附加多個記錄更容易。

我還使用 log4php+syslog-ng 來實時集中日志記錄。 我有 log4php 日志到 syslog,然后將日志轉發到我的中央服務器。 這在較大的集群上非常有用。 一個警告是系統日志消息有長度限制,因此您可能會冒更長的消息被截斷的風險。

如果您使用基於文件的日志記錄或基於數據庫的日志記錄,最大的性能損失將是文件/表鎖定。 基本上,如果客戶端 A 和客戶端 B 在相對較短的時間范圍內連接,則客戶端 B 會在繼續之前等待釋放對命中文件/表的鎖定。

基於文件的機制的問題在於文件鎖定對於確保您的點擊不會被破壞至關重要。 解決這個問題的唯一方法是實現一個隊列來延遲寫入文件。

使用數據庫日志記錄,您至少可以執行以下操作[使用 MyISAM 的 MySQL]:

INSERT DELAYED INTO `hits` ...

12.2.5.2。 INSERT DELAYED 語法以獲取更多信息。

進入文件會更快,但進入數據庫會更好。

一切都取決於您的基礎設施和限制。 如果磁盤很慢,則寫入會很慢。 如果 SQL 服務器被請求滯后,則插入會很慢。 平面文件可能是最好的方法,但我會編寫您的代碼或使用現有代碼 (PEAR::Log),以便您可以隨意更改提供程序和存儲方法。

幾點考慮:

  1. 您認為您希望將日志數據與數據庫中的其他數據連接起來嗎? 如果是這樣,db insert 的開銷可能是合理的,因此可以輕松利用現有關系。
  2. 記錄數據庫中的數據是否可以讓您大大減少記錄的數據量(由於數據庫中的現有關系)? 例如,用戶活動數據庫中的日志可能只是一個包含用戶 ID、活動 ID 和時間戳的表。 文件中這種精益化的日志文件不會是人類可讀的。 根據您的需要,您至少需要在日志文件中捕獲一些用戶數據,以確保它本身是有用的和人類可讀的。
  3. 您是否有機會在前端或通過管理工具利用此日志數據? 如果是這樣,DB 寫入可能更可取。

正如其他人提到的 - 這取決於很多事情,例如流量、磁盤速度等。您必須測試這兩種情況。

在測試 MySQL 時,同時嘗試 MyISAM 和 INNODB。 理論上,Innodb 會表現得更好,因為它有行級鎖。

如果這是針對數據庫驅動的站點,為什么不只使用 Apache 或 IIS 的內置日志記錄功能,以及合適的報告工具(例如AWStats等),總有Google Analytics(分析)

AWStats 和網絡服務器日志記錄是我的偏好 - 無論如何,您基本上可以免費獲得它 - 即使您沒有進行流量分析,您仍然可以考慮自己解析 Apache 訪問日志文件以進行您需要執行的任何批處理。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM