2009-07-21 14 views
7

Ho un database sqlite3 sul mio harddrive (file.db) con 5 tabelle. Vorrei copiare 3 di queste tabelle in un database in memoria (: memoria :).PHP/SQLite - Copia di una tabella dal disco alla memoria

C'è un modo semplice per farlo utilizzando il formato PDO di PHP5?

+0

Sto anche cercando di fare questo per il mio test di unità. Il file db sqlite avrà tutti i dati di test. Ma non voglio che i test cambino, quindi voglio copiare il db in: memory: prima di eseguire i test su di esso. Solo dando una ragione qualcuno potrebbe voler fare questo. – andho

risposta

10

Non una soluzione specifica-PDO che può o non può essere sufficiente nel tuo caso:

  • creare una: la memoria: banca dati
  • Attach il file di database esistente
  • CREATE TABLE ... AS SELECT * FROM ...
  • Detach il file di database

edit: un esempio
primo un database di esempio memorizzato in mydb.sq3

<?php 
$pdo = new PDO('sqlite:mydb.sq3'); 
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); 

$pdo->exec('CREATE TABLE foo(x INTEGER PRIMARY KEY ASC, y, z)'); 

$stmt = $pdo->prepare("INSERT INTO foo (x,y,z) VALUES (:x,:y,:z)"); 
$stmt->bindParam(':x', $x); 
$stmt->bindParam(':y', $y); 
$stmt->bindParam(':z', $z); 

for($x=0; $x<100; $x++) { 
    $y = $x*2; 
    $z = $x*2+1; 
    $stmt->execute(); 
} 

ora abbiamo una: la memoria: database e si desidera trasferire la tabella foo

<?php 
$pdo = new PDO('sqlite::memory:'); 
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); 

$pdo->exec('ATTACH "mydb.sq3" as filedb'); 
$pdo->exec('CREATE TABLE bar AS SELECT * FROM filedb.foo'); 
$pdo->exec('DETACH filedb'); 

Fatto. Ma diamo uno sguardo al tavolo sqlite_master

foreach($pdo->query('SELECT sql FROM sqlite_master') as $row) { 
    echo $row['sql']; 
} 

questa stampa

CREATE TABLE bar(x INT,y,z) 

Il dichiarazione INTEGER PRIMARY KEY ASC è perduto. Potrebbe essere sufficiente però ....

+0

sì, ho trovato questo in linea ma non ho potuto trovare un modo per farlo con php-pdo. –

+3

aggiungerà un esempio – VolkerK

4

Se è quello che devi fare, la risposta di VolkerK è quella che fornirò, ma sento che devo segnalare che leggerete il contenuto di quelle tabelle in memoria ogni volta che si esegue quel codice (ogni volta che la pagina viene caricata?), quindi potrebbe essere meglio interrogare i file di dati dal disco.

+2

Per i test questo può davvero avere senso in quanto la suite può rimanere in memoria tra tutti i test. – hakre

1

Si noti che è possibile utilizzare sempre una sorta di meccanismo di memoria condivisa (ad esempio APC, memcache, ecc.) Per mantenere i database in memoria di sqlite persistenti attraverso le connessioni.

+0

Potresti spiegare come farlo qui: http://stackoverflow.com/questions/9104698/does-it-possible-to-store-sqlites-memory-tables-in-apc? – xun

0

È possibile eseguire il dump del database alla fine della connessione, salvarlo come variabile apc e quindi caricare ed eseguire nuovamente da apc all'inizio della successiva esecuzione.

0

L'utilizzo del metodo descritto da VolkerK ha raddoppiato le prestazioni del mio codice quando si utilizzava un database sqlite di ~ 150Mb.

Il caricamento del database in un dl sqlite in memoria non ha richiesto altre modifiche al codice esistente.

Il mio caso d'uso era l'elaborazione in batch dei dati quindi non dovevo affrontare i problemi di Wez Furlong.

Leggere i dati in memoria era sorprendentemente veloce. L'intero 150Mb è stato caricato in memoria da SSD in meno di due secondi. Sembrava troppo bello per essere vero, quindi ho controllato e ricontrollato i dati.

Mille grazie a VolkerK per una soluzione magica!

Ho anche scoperto che quando ho indicizzati le tabelle in memoria le mie domande eseguite tre volte più veloce

//adapting VolkerK's example... 
//loop through tables from the local sqlite db 
$tables = array('companies', 'directors', 'previous_names'); 
foreach($tables as $table){ 
    //load each table into memory 
    $pdo->exec("CREATE TABLE $table AS SELECT * FROM filedb.$table"); 

    //index each table on the relevant columns 
    $pdo->exec("CREATE INDEX IF NOT EXISTS `".$table."_company_number` 
       ON $table (`company_number`);"); 
} 
Problemi correlati