6

サンプルアプリ。従業員情報があり、payrollやposなどのさまざまなアプリケーションからアクセスされます。1つのデータベースに従業員データがあり、給与データとPOSがそれぞれ別々のデータベースにあります。

私は以下のようなデータベース接続クラスを持っているので、データベースへの接続を取得したいときはいつでも実行します$conn = Database::getInstance(db1)

うまく機能しますが、基本的には非常に遅いです。アプリの実行が非常に遅くなります。なぜそれがそうなのか、それともこれを行うためのより良いが代替のアイデアであるのかについてのヒントはありますか?

どんな助けでも大歓迎です

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

5 に答える 5

1

常に新しいオブジェクトを作成しないでください。何が起こっているのかというと、別のデータベースタイプを要求するたびに、新しいキーワードを使用してそのデータベースタイプを再作成しているということです(ただし、これを使用するコードを見ずに確認するのは困難です)。

$ _instanceは静的メンバーであるため、データベースタイプを変更すると、常に上書きされます。そのことについては$db_typeもそうです

これはあなたがしていることにはやり過ぎですが(DBごとに2つの変数があるだけではないのはなぜですか?)、次のようなものを試すことができます。

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

注:構文がオフになっている可能性があります。パターンを示したかっただけです。

于 2012-11-02T01:16:19.750 に答える
1

このデザインで。データベースを変更すると、前のデータベースへの接続が破棄されます。

接続ごとに個別のオブジェクトを作成してから、接続オブジェクトを切り替えます。

また、これは同じ理由でスレッドセーフではありません。複数の関数が同時にこれにヒットしている場合、ロードが完了する前に一方が他方を切断できます。

実際には、関数ごとに新しい接続オブジェクトを作成するだけで、関数や他のオブジェクト間で共有しないでください。

于 2012-11-02T01:16:44.833 に答える
1

あなたが絶えず接続を切り替えているという事実以外に、なぜそれが物事を遅くするのか分かりません。ここで提案できる唯一のことは、複数の接続を切り替えるのではなく、許可することです。

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');

このようなものを使用すると、実際に一度に複数の開いている接続を管理でき、それらは遅延ロードされます。つまり、PDO接続を要求するまで、実際にはインスタンス化しないでください。Database::getConnection同様に、いつでも追加のDSNとクレデンシャルを挿入できます。個人的には、クラス内の定数を使用してフォーム構成をハードコーディングするのではなく、フォーム構成をクラスに直接ロードします。次に、次のようになります。

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

Database::loadConnections($config);
于 2012-11-02T01:28:44.090 に答える
0

遅延読み込みも使用するように変更してはどうでしょうか。請負業者のデータベースに接続する必要はありません。データベースが最初に必要になったときにのみ接続します。そうすれば、ページが接続の1つだけを使用する場合、他のデータベースを待つ必要はありません。

于 2012-11-02T01:14:31.840 に答える
0

DB_HOSTとDB_HOST_2の値を確認してください。以前、MySQLは「127.0.0.1」を使用して接続するのが非常に遅いことがわかりましたが、「localhost」を使用して即座に接続します。

サーバーのセットアップ方法によって異なりますが、役立つかもしれないと思っただけです。

于 2012-11-02T01:20:22.320 に答える