2009-07-21 11 views
7

Tengo una base de datos sqlite3 en mi disco duro (file.db) con 5 tablas. Me gustaría copiar 3 de estas tablas en una base de datos en memoria (: memoria :).PHP/SQLite - Copia de una tabla del disco a la memoria

¿Hay una manera simple de hacerlo usando el formato PDO de PHP5?

+0

También estoy tratando de hacer esto para mis pruebas unitarias. El archivo sqlite db tendrá todos los datos de prueba. Pero no quiero que las pruebas cambien esto, así que quiero copiar el archivo db en: memoria: antes de ejecutar las pruebas en él. Simplemente dando una razón por la que alguien podría querer hacer esto. – andho

Respuesta

10
No

una solución-pdo específico que puede o no ser suficiente en su caso:

  • crear una: la memoria: la base de datos
  • Attach el archivo de base de datos existente
  • CREATE TABLE ... AS * SELECT ...
  • Detach el archivo de base de datos

edición: un ejemplo
Primera ejemplo una base de datos almacenada en 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(); 
} 

Ahora tenemos una: la memoria: base de datos y desea transferir la tabla 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'); 

Hecho. Sin embargo, vamos a echar un vistazo a la tabla sqlite_master

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

este imprime

CREATE TABLE bar(x INT,y,z) 

El INTEGER PRIMARY KEY ASC declaración se pierde. Puede ser suficiente sin embargo ....

+0

Sí, encontré esto en línea, pero no pude encontrar una manera de hacer esto con php-pdo. –

+3

agregará un ejemplo – VolkerK

4

Si eso es lo que tiene que hacer, entonces la respuesta de VolkerK es la que yo proporcionaría, pero siento que debo señalar que va a leer los contenidos de esas tablas en la memoria cada vez que ejecuta ese código (¿cada vez que se carga esa página?), por lo que sería mejor simplemente consultar los archivos de datos desde el disco.

+2

Para las pruebas esto realmente puede tener sentido ya que el paquete puede permanecer en la memoria en todas las pruebas. – hakre

1

Tenga en cuenta que siempre se puede utilizar algún tipo de mecanismo de memoria compartida (por ejemplo, APC, Memcache, etc.) para mantener las bases de datos en memoria de sqlite persistentes a través de las conexiones.

+0

¿Podría explicar cómo hacerlo aquí - http://stackoverflow.com/questions/9104698/does-it-possible-to-store-sqlites-memory-tables-in-apc? – xun

0

Puede volcar la base de datos al final de la conexión, guardarla como una variable apc y luego cargar y ejecutar de nuevo desde la APC al comienzo de la siguiente ejecución.

0

El uso del método descrito por VolkerK duplicó aproximadamente el rendimiento de mi código cuando se usa una base de datos sqlite de ~ 150Mb.

Cargando la base de datos en una memoria en tiempo real sqlite db no requirió ningún otro cambio en mi código existente.

Mi caso de uso era la información de procesamiento por lotes, así que no tuve que lidiar con los problemas que resalta Wez Furlong.

La lectura de los datos en la memoria fue sorprendentemente rápida. Todo el 150Mb se cargó en la memoria de SSD en menos de dos segundos. Parecía demasiado bueno para ser verdad, así que revisé y volví a verificar los datos.

¡Muchas gracias a VolkerK por una solución mágica!

También encontré que cuando indexado las tablas en memoria mis consultas ejecutadas tres veces más rápido

//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`);"); 
} 
Cuestiones relacionadas