2011-08-31 6 views
17

Ho pochi script caricati da cron abbastanza spesso. Al momento non memorizzo nessun registro, quindi se uno script non viene caricato, non lo saprò fino a quando non vedo i risultati - e anche quando noterò che i risultati non sono corretti, non posso fare nulla visto che non lo faccio so quale script ha fallito.Cosa c'è di più efficiente: la memorizzazione dei registri nel database o nei file sql?

Ho deciso di archiviare i registri, ma non sono ancora sicuro di come farlo. Quindi, la mia domanda è - che cosa è più efficiente - la memorizzazione dei registri nel database o nei file sql?

Posso creare la tabella 'logs' nel mio database mysql e memorizzare ciascun log in una riga separata, oppure posso semplicemente usare php's file_put_contents o fopen/fwrite per archiviare i log in file separati.

I miei script aggiungono approssimativamente 5 registri (in totale) al minuto mentre si lavora. Ho fatto alcuni test per determinare cosa è più veloce: fopen/fwrite o mysql's insert. Ho fatto un ciclo di istruzioni "insert" 3000 volte per creare 3000 righe e ho fatto un ciclo di fopen/fwrite 3000 volte per creare 3000 file con testo di esempio. Fwrite eseguito 4-5 volte più veloce dell'inserto di sql. Ho fatto un secondo ciclo - ho fatto un ciclo di istruzioni 'select' e l'ho assegnato a una stringa 3000 volte - ho anche aperto 3000 file usando 'fopen' e assegnato i risultati alla stringa. Il risultato è stato lo stesso: fopen/fwrite ha terminato l'operazione 4-5 volte più velocemente.

Quindi, per tutti i programmatori esperti, qual è la vostra esperienza con l'archiviazione dei registri? Qualche consiglio?

// 04.09.2011 EDIT - Grazie a tutti per le vostre risposte, hanno aiutato molto. Ogni post era prezioso, quindi era piuttosto difficile accettare solo una risposta ;-)

+0

@the lentezza è nella testa della dichiarazione 'insert'. Se tu dovessi aggiungere i dati a un file CSV e leggere che nell'uso di 'load data infile', i 4-5 tempi si fonderebbero rapidamente in 2 volte, 1x per scrivere il file CSV, 1x per caricare i dati in infile. – Johan

+1

@firian - Devi solo attivare lo script per inviare un'email (contiene i dettagli) quando c'è un problema – ajreal

+0

Puoi usare un database di cache come redis o memcache e un processo per mantenere tutto questo in un mysql. Anche tu puoi usare MongoDB direttamente o usare redis bridge. Redis è veramente veloce, mongo è il più lento. MySQL è davvero molto lento xD. Anche tu puoi usare qualche servizio di log esterno come loggly.com – user1710825

risposta

5

È possibile utilizzare un componente come Zend_Log che supporta in modo nativo il concetto di writer collegati alla stessa istanza di registro. In questo modo è possibile registrare lo stesso messaggio in uno o più luoghi diversi senza la necessità di modificare il codice di registrazione. E puoi sempre cambiare il tuo codice per sostituire il sistema di log o aggiungerne uno nuovo in un modo semplice.

Per la tua domanda, penso che il registro dei file sia più semplice e appropriato se tu (sviluppatore) è l'unico che ha bisogno di leggere i messaggi di log.

Accedere a db se è necessario che altre persone legga i registri in un'interfaccia Web o se è necessario cercare i registri. Come qualcun altro ha sottolineato anche questioni relative alla concorrenza, se hai molti utenti accedi a db potresti scalare meglio.

Infine, una frequenza di registro di 5 messaggi al minuto non richiede quasi nessuna CPU per l'applicazione, quindi non è necessario preoccuparsi delle prestazioni. Nel tuo caso comincerei con i file di log e poi cambierei (o aggiungerei altri scrittori) se i tuoi requisiti cambieranno.

+0

lo strumento più complesso che stai utilizzando, meno stabile è. Mantieni la semplicità e utilizza file di registro semplici. –

+0

@ Col.Shrapnel lo strumento più complesso che stai utilizzando, più flessibile è. Inoltre, Zend_Framework ha più di tre anni ed è ben testato, dovrebbe essere abbastanza solido, non credi? – Fabio

+0

la flessibilità non è tra le caratteristiche più importanti del logging. ma la tolleranza d'errore è. Nel caso in cui tu voglia il tuo logger con blackjack e hookers - per favore, fai * post * processing, usa qualunque analizzatore di log che sarà felice di mettere i tuoi log in database, base lunare o quant'altro. –

11

I registri utilizzando i file sono più efficienti, tuttavia i registri archiviati nel database sono più facili da leggere, anche da remoto (è possibile scrivere un frontend Web se richiesto, per esempio).

Si noti tuttavia che la connessione e l'inserimento di righe nel database sono soggette a errore (server di database inattivo, password errata, fuori risorse), quindi dove registrare tali errori se si è deciso di utilizzare il database?

+7

Come registreresti un errore I/O nel file di log? – cypher

+0

Gli errori di I/O sono meno comuni. – trojanfoe

+1

Quindi come lo registreresti? – cypher

1

Scrivere il file system dovrebbe essere sempre più veloce.

Che tuttavia dovrebbe essere la vostra preoccupazione. Entrambe le operazioni di inserimento e scrittura in un file system sono operazioni rapide. Quello di cui devi preoccuparti è cosa succede quando il tuo database fallisce. Mi piace scrivere su entrambi, quindi c'è sempre un log se qualcosa va storto ma hai anche la facilità di cercare da un database.

+0

citazione necessaria. Methinks scrivendo su un file ha causato un blocco di file completo su ogni scrittura, se il database (motore) supporta il blocco delle righe del DB può essere molto più veloce. – Johan

+1

@Johan non ci sono file nei file. e il database mantiene i dati in nessun posto ma con i file –

+0

@Col, un database può utilizzare alcuni trucchi per rendere le cose più veloci, è possibile utilizzare un motore di memoria o una tabella partizionata distribuita su dischi diversi per rendere gli inserti più veloci di quanto si possa fare in un appartamento file. Il mio punto è che il filesystem è ** non sempre ** più veloce. – Johan

0

La registrazione degli errori è meglio limitata ai file secondo me, perché se c'è un problema con il database, è ancora possibile registrarlo. Ovviamente questa non è un'opzione se la registrazione degli errori richiede una connessione al database!

Quello che posso anche dire però, è che la registrazione generale è qualcosa che lascio all'interno del database, ma questo vale solo se si sta facendo un sacco di registrazione per gli audit trail ecc

1

Dipende dalla dimensione dei registri e dal livello di concorrenza. A causa dell'ultimo, il tuo test è completamente non valido: se ci sono 100 utenti sul sito e hai detto 10 thread che scrivono sullo stesso file, fwrite non sarà così veloce. Una delle cose che fornisce RDBMS è il controllo della concorrenza.

Dipende dai requisiti e dal lotto di analisi che si desidera eseguire. Basta leggere i record è facile, ma per quanto riguarda l'aggregazione di alcuni dati in un periodo definito.

I siti Web di grandi dimensioni utilizzano sistemi come Scribe per scrivere i propri registri.

Se si parla di 5 record al minuto, tuttavia, si tratta di un carico veramente basso, quindi la domanda principale è come leggerli. Se il file è adatto alle tue esigenze, vai con il file. Generalmente, le scritture append-only (normalmente per i log) sono molto veloci.

1

La velocità non è tutto. Sì, è più veloce scrivere sui file, ma è molto più veloce per trovare ciò che è necessario nei log se si trovano in un database. Diversi anni fa ho convertito il nostro CMS da un registro basato su file in una tabella Mysql. Il tavolo è meglio

6

Commentando i risultati.

Per quanto riguarda la scrittura del file, probabilmente hai ragione.
Per quanto riguarda la lettura, sei completamente sbagliato.

scrittura su un database:

  1. MyISAM blocca l'intera tabella su inserti, causando un conflitto di blocco. Usa InnoDB, che ha il blocco delle righe.
  2. Contrario a 1. Se si desidera eseguire ricerche di testo completo nel registro. Usa MyISAM, supporta gli indici di testo completo.
  3. Se vuoi essere veramente veloce puoi usare il motore memory, questo scrive la tabella nella RAM. Trasferisci i dati su una tabella basata su disco quando il carico della CPU è basso.

lettura dal database

Questo è dove il database brilla veramente.
È possibile combinare tutti i tipi di informazioni da voci diverse, molto più velocemente e facilmente di quanto si possa mai fare da un file flat.

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

Se si dispone di indici sui campi utilizzati nella clausola where il risultato tornerà quasi istantaneamente, prova a fare che in un file flat.

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

Non importa il fatto che la tabella non è normalizzata, questo sarà molto molto più lento e più difficile da fare con un file flat.
È davvero un gioco da ragazzi.

0

Personalmente, preferisco i file di log così ho creato due funzioni:

<?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); 
    } 
} 
?> 

Mi definisco una costante o due (io uso ACTIVITY_LOG e error_log entrambi impostati lo stesso file in modo che non c'è bisogno di fare riferimento a due file affiancati per ottenere una visione generale della corsa) e chiamare come appropriato. Ho anche creato una cartella dedicata (/ var/log/phplogs) e ogni applicazione che scrivo ha il proprio file di registro. Infine, ruoto i registri in modo da avere un po 'di storia a cui fare riferimento per i clienti.

L'uso libero delle funzioni di cui sopra significa che posso tracciare l'esecuzione di app abbastanza facilmente.

+0

Perché non solo error_log ("Message") ;? –

+0

Perché eseguo più applicazioni contemporaneamente e non voglio scorrere un singolo file di registro (potenzialmente ** di grandi dimensioni **) alla ricerca di errori per una particolare applicazione. E prima che qualcuno dica "Molti errori? Codifica scadente!", Accedo a molti servizi esterni che hanno la capacità di fallire quindi devo registrare anche questo – DaveyBoy

+0

così, stai raccogliendo gli errori nativi di PHP in singoli (potenzialmente grandi) file di registro, ma quelli manuali vanno nei registri più piccoli. Strana configurazione, se mi chiedi –

1

Penso che la memorizzazione dei registri nel database non sia una buona idea. I vantaggi di archiviare i registri nei database su file è che è possibile analizzare i registri molto più facilmente con la potenza di SQL, ma gli svantaggi sono che si deve pagare molto più tempo per la manutenzione del database. È preferibile impostare un server di database separato per memorizzare i registri o si potrebbe ottenere troppo registro INSERT che diminuirà le prestazioni del database per l'utilizzo di produzione; inoltre, non è facile eseguire la migrazione, archiviare i registri nel database, confrontati con i file (logrotate, ecc.).

Al giorno d'oggi è necessario utilizzare un sistema di registrazione ricco di funzioni speciali per gestire i registri, ad esempio, logstash (http://logstash.net/) ha collettore di log, filtro e può memorizzare il log in sistemi esterni come elasticsearch, combinato con un bellissimo frontend per visualizzare e analizzare i tuoi registri.

Rif: