2011-11-22 7 views
11

Ho bisogno di memorizzare una quantità enorme di testo nel database mysql. Saranno milioni di record con il tipo di campo LONGTEXT e la dimensione del database sarà enorme.Compressione del testo prima di memorizzarlo nel database

Quindi, vorrei chiedere, se esiste un modo sicuro per comprimere il testo prima di memorizzarlo nel campo TESTO per risparmiare spazio, con la possibilità di estrarlo indietro se necessario?

Qualcosa di simile:

$archived_text = compress_text($huge_text); 
// saving $archived_text to database here 
// ... 

// ... 
// getting compressed text from database 
$archived_text = get_text_from_db(); 
$huge_text = uncompress_text($archived_text); 

C'è un modo per fare questo con PHP o MySQL? Tutti i testi sono codificati in utf-8.

UPDATE

La mia domanda è un grande sito web della letteratura in cui gli utenti possono aggiungere i loro testi. Ecco la tabella che ho:

CREATE TABLE `book_parts` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `book_id` int(11) NOT NULL, 
    `title` varchar(200) DEFAULT NULL, 
    `content` longtext, 
    `order_num` int(11) DEFAULT NULL, 
    `views` int(10) unsigned DEFAULT '0', 
    `add_date` datetime DEFAULT NULL, 
    `is_public` tinyint(3) unsigned NOT NULL DEFAULT '1', 
    `published_as_draft` tinyint(3) unsigned NOT NULL DEFAULT '0', 
    PRIMARY KEY (`id`), 
    KEY `key_order_num` (`order_num`), 
    KEY `add_date` (`add_date`), 
    KEY `key_book_id` (`book_id`,`is_public`,`order_num`), 
    CONSTRAINT FOREIGN KEY (`book_id`) REFERENCES `books` (`id`) ON DELETE CASCADE 
) ENGINE=InnoDB DEFAULT CHARSET=utf8 

Attualmente ha circa 800k record e pesi 4 GB, il 99% delle query sono SELECT. Ho tutte le ragioni per pensare che i numeri aumentino schematicamente. Non mi piacerebbe archiviare i testi nei file perché c'è una logica piuttosto pesante e il mio sito web ha parecchi successi.

+0

Se si memorizzano dati binari, utilizzare un campo BLOB, non testo. – Brad

+1

Si consiglia di riconsiderare il proprio veto sull'archiviazione basata su file. Non sono sicuro di cosa intenda per "logica pesante", ma non vedo come la memorizzazione dei testi nel database sia automaticamente migliore dei file per un sito con molto traffico. – grossvogel

risposta

12

Hai intenzione di indicizzare questi testi. Quanto è grande la lettura caricata su questi testi? Inserisci il carico?

È possibile utilizzare la compressione dei dati InnoDB in modo trasparente e moderno. Vedi docs per maggiori informazioni.

Se hai davvero testi enormi (ad esempio, ogni testo è superiore a 10 MB), la buona idea non è salvarli in Mysql. Negozio compresso da testi gzip nel file system e solo puntatori e meta in mysql. Puoi espandere facilmente lo spazio di archiviazione in futuro e spostarlo ad es. DFS.

Aggiornamento: un altro vantaggio rispetto all'archiviazione di testi all'esterno di Mysql: DB rimane piccolo e veloce. Meno: alta probabilità di incoerenza dei dati.

Aggiornamento 2: se avete molto resourses di programmazione, per favore, dare uno sguardo su progetti come questo: http://code.google.com/p/mysql-filesystem-engine/.

Aggiornamento finale: in base alle informazioni, è possibile utilizzare solo la compressione InnoDB - è lo stesso di ZIP. Si può iniziare con questi params:

CREATE TABLE book_parts 
(...) 
ENGINE=InnoDB 
ROW_FORMAT=COMPRESSED 
KEY_BLOCK_SIZE=8; 

Più tardi avrete bisogno di giocare con KEY_BLOCK_SIZE. Vedi SHOW STATUS LIKE 'COMPRESS_OPS_OK' e SHOW STATUS LIKE 'COMPRESS_OPS'. Il rapporto tra questi due parametri deve essere vicino a 1.0: Docs.

+0

Se stai usando InnoDB, questo è il modo di partire. Utilizzo di un motore che non esegue la compressione, tuttavia ... Inoltre, vedo un sacco di motivi per non "archiviare solo i puntatori ai file" nel database (e un sacco di motivi per farlo - TIMTOWTDI, e dipende davvero cosa ti serve) – Romain

+0

@ Oroboros102 per favore guarda l'aggiornamento. Ho capito bene, che la compressione di innodb comprime solo gli indici? Questo non è il mio caso ... –

+0

No, la compressione è usata sia per i dati che per tutti gli indici (PK, secondario, composto). – Oroboros102

7

Se si sta comprimendo (ad esempio gzip), quindi non utilizzare campi di testo di alcun tipo. Non sono binari-sicuri. I dati che entrano/escono dai campi di testo sono soggetti alla traduzione dei set di caratteri, che probabilmente (sebbene non necessariamente) manipolano i dati compressi e forniscono un risultato corrotto quando si recupera/decomprime il testo.

Utilizzare invece campi BLOB, che sono binari-trasparenti e non a qualsiasi traduzione dei dati.

+0

Grazie per le informazioni sul tipo di dati. Ma per quanto riguarda la compressione? –

+0

La compressione rimuoverà la possibilità di cercare nel testo, poiché dovresti eseguire la decompressione per eseguire nuovamente il test non elaborato. Se non utilizzerai mai il DB per rovistare il testo, non salvare il testo compresso (o grezzo) nel DB in primo luogo. Memorizzalo esternamente in un file e memorizza alcuni riferimenti (nomefile/percorso) nel DB. –

+0

gzcompress funziona molto bene con questo approccio, ma considera: http://www.mysqlperformanceblog.com/2008/01/11/mysql-blob-compression-performance-benefits/ –

2

Non ci sono benefici nella compressione di testi grandi in un database.

Qui ci sono i problemi che si potrebbero affrontare nel lungo periodo:

  • Se il server si blocca i dati possono essere difficili da recuperare.
  • Non ideale per la ricerca.
  • Ci vuole più tempo per trasferire i dati tra il server mysql e il browser.
  • In termini di tempo per il backup (non utilizzando la replica).

penso che la memorizzazione di questi grandi testi in un file su disco sarà più facile per:

  • backup distribuiti (rsync).
  • PHP per gestire il caricamento di file.
+0

Non sono d'accordo. Il tempo necessario per decomprimere un flusso gzip è irrilevante su qualsiasi server normale, rispetto alla latenza online è possibile ignorarlo completamente. Non è necessario cercare in ogni campo di testo, spesso è sufficiente accedervi. – John

5

Potrebbe essere preferibile definire il campo di testo come blob e comprimere i dati in PHP per risparmiare costi nella comunicazione.

CREATE TABLE book_parts (
    ...... 
    content blob default NULL, 
    ...... 
) 

In PHP, utilizzare gzcompress e gzuncompress.

1

È possibile utilizzare le funzioni php gzdeflate e gzinflate per il testo.