2012-11-02 16 views
6

app di esempio, con informazioni sui dipendenti e accesso a diverse applicazioni come buste paga e pos. Ho i dati dei dipendenti in un database, i dati del libro paga e pos in database separati ciascuno.Singleton con più database

ho una classe di connessione al database come di seguito, quindi ogni volta che voglio ottenere una connessione a un db faccio solo $conn = Database::getInstance(db1).

funziona alla grande, ma è fondamentalmente molto lento. fa funzionare l'app molto lentamente. Qualche consiglio sul perché è così o meglio ancora idee alternative per fare questo?

qualsiasi aiuto sarà molto apprezzato

<?php  
class Database { 
     private $db; 
     static $db_type; 
     static $_instance; 

     private function __construct($db){ 
      switch($db) { 
       case "db1": 
        try{ 
         $this->db = new PDO("mysql:host=" . DB_HOST . ";dbname=" . DB_NAME, DB_USER, DB_PASSWORD); 
        } 
        catch(PDOException $e){ 
         print "Error!: " . $e->getMessage() . "<br />"; 
         die(); 
        } 
       break; 
       case "db2": 
        try{ 
         $this->db = new PDO("mysql:host=" . DB_HOST_2 . ";dbname=" . DB_NAME_2, DB_USER_2, DB_PASSWORD_2); 
        } 
        catch(PDOException $e){ 
         print "Error!: " . $e->getMessage() . "<br />"; 
         die(); 
        } 
       break; 
      } 
      self::$db_type = $db; 

     } 

     private function __clone(){} 

     static function getInstance($db_type){ 
      if(!(self::$_instance) || $db != self::$db_type){ 
       self::$_instance = new self($db_type); 
      } 
      return self::$_instance; 
     } 
    } 
?> 
+1

Non ci vuole molto tempo per stabilire una connessione al database, e non penserei che la tua app sarebbe "lenta" nel complesso perché hai diversi DB da connettere a . I database sono locali? o su un server remoto? I database – Dan

+0

sono tutti locali. Attualmente sto usando questo approccio e il suo caricamento richiede parecchio tempo rispetto a quando ho tutto in un solo db –

+0

Puoi aiutare a trovare la linea specifica che rallenta le cose catturando microtime() prima dopo certe linee. Se può essere d'aiuto se è possibile isolare in modo specifico il problema sulla linea che si collega al database. – Dan

risposta

1

Con questo design. Se si modificano i database, questo distrugge la connessione al database precedente.

Creare oggetti separati per ogni connessione, quindi passare tra gli oggetti di connessione.

Inoltre, questo non è thread-safe per la stessa ragione. Se più funzioni lo colpiscono allo stesso tempo, è possibile disconnettere l'altro prima del caricamento completato.

Dovresti davvero creare un nuovo oggetto di connessione per ogni funzione e non condividerlo tra funzioni o altri oggetti.

+0

Awesome! Modificato su un array che tiene gli oggetti, funziona perfettamente! –

+2

per gli altri per riferimento: 'funzione getInstance statico ($ tipo_db = "") { \t \t \t \t if (isset (connessioni self :: $ [$ tipo_db])) { \t \t \t self :: $ connessioni [ $ db_type] = new self ($ db); \t \t} \t \t return self :: $ connections [$ db_type]; \t} ' –

+0

@ user1239663 Qual era il tuo nuovo codice completato? – johnny

0

ne dite di cambiarla utilizzare anche il carico pigro. Non è necessario connettersi ai database nel contraente. Connettiti solo quando il database è richiesto per la prima volta. In questo modo, se la pagina utilizza solo una delle connessioni, non è necessario attendere gli altri database.

+0

mi dispiace non capisco cosa intendi, potresti spiegare un po 'di più –

1

Non creare nuovi oggetti costantemente. Quello che succede è che ogni volta che richiedi un altro tipo di database, lo stai ricreando tramite la nuova parola chiave (anche se difficile da confermare senza vedere il codice che usa questo).

$ _stance è un membro statico, quindi si sovrascrive costantemente quando si modifica il tipo di database. così è $ tipo_db per quella materia

Mentre questo è eccessivo per quello che stai facendo (perché non basta avere due variabili per ogni DB?), si potrebbe provare qualcosa di più simile a questo:

<?php  
class Database { 
     private $db; 
     static $db_types; 


     private function __construct($db){ 
      switch($db) { 
       case "db1": 
        try{ 
         $db_types[$db] = new PDO("mysql:host=" . DB_HOST . ";dbname=" . DB_NAME, DB_USER, DB_PASSWORD); 
        } 
        catch(PDOException $e){ 
         print "Error!: " . $e->getMessage() . "<br />"; 
         die(); 
        } 
       break; 
       case "db2": 
        try{ 
         $db_types[$db] = new PDO("mysql:host=" . DB_HOST_2 . ";dbname=" . DB_NAME_2, DB_USER_2, DB_PASSWORD_2); 
        } 
        catch(PDOException $e){ 
         print "Error!: " . $e->getMessage() . "<br />"; 
         die(); 
        } 
       break; 
      } 


     } 

     private function __clone(){} 

     static function getInstance($db_type){ 
      if(!inarray($db_types[$db_type]){ 
       $db_types[$db_type] = new self($db_type); 
      } 
      return $db_types[$db_type]; 
     } 
    } 
?> 

NOTA: la sintassi è probabilmente disattivata. Volevo solo dimostrare il modello.

+0

fammi provare e ti farò sapere. –

+0

è riuscito a farlo funzionare, ma non ha risolto il problema di velocità. ci vuole ancora un bel po 'per caricare. Suppongo che forse qualcos'altro sta causando questo problema, ma proverò la soluzione da prodigitalson per confrontare poi saprò –

0

Verificare il valore di DB_HOST e DB_HOST_2. In precedenza ho trovato MySQL estremamente lento a connettersi usando "127.0.0.1", ma collegandomi istantaneamente usando "localhost".

Dipende dal modo in cui è configurato il server, ma ho pensato che potrebbe essere d'aiuto.

1

Non capisco perché ciò renderebbe le cose lente a parte il fatto che tu stia cambiando continuamente conncections. L'unica cosa che posso suggerire è quello di consentire connessioni multiple invece di loro passaggio:

class Database { 
    protected static $connections; 

    protected $activeConnections = array(); 

    protected static $instance; 

    protected function __construct() { 

    } 

    public static loadConnections(array $connections) { 

     self::$connections = $connections; 
    } 

    public function getConnection($name) 
    { 
     if(!isset($this->activeConnections[$name]) { 
      if(!isset(self::$connections[$name]) { 
      throw new Exception('Connection "' . $name . '" is not configured.'); 
      } 

      $this->activeConnections[$name] = new PDO(
       self::$connections[$name]['dsn'], 
       self::$connections[$name]['username'], 
       self::$connections[$name]['password'] 
     ); 

     } 

     return $this->activeConnections[$name]; 
    } 
} 

// usage 

Database::loadConnections(array(
    'db1' => array(
     'dsn' => "mysql:host=" . DB_HOST . ";dbname=" . DB_NAME, 
     'user' => DB_USER, 
     'password' => DB_PASSWORD, 
    ), 
    'db2' => array(
     'dsn' => "mysql:host=" . DB_HOST2 . ";dbname=" . DB_NAME2, 
     'user' => DB_USER2, 
     'password' => DB_PASSWORD2, 
))); 

$conn1 = Database::getInstance()->getConnection('db1'); 
$conn2 = Database::getInstance()->getConnection('db2'); 

Usando qualcosa di simile si può effettivamente manange più connessioni aperte alla volta, e sono caricato in modo pigro - il che significa che non avete in realtà crea un'istanza una connessione PDO fino a quando non la richiedi con Database::getConnection Allo stesso modo puoi inserire ulteriori DSN e credenziali in qualsiasi momento. Personalmente vorrei caricare la configurazione del modulo direttamente sulla classe invece di codificarli con costanti con la classe.quindi potresti qualcosa del tipo:

// gives us an array 
$config = Config::load('path/to/db/config.yml'); 

Database::loadConnections($config); 
+0

fammi provare e ti farò sapere come va –

+0

scusa, manca una funzione statica getInstance()? –

+0

Non è una classe completa ... ho appena delineato le differenze con le tue :-) – prodigitalson