1

これは私が DB にアクセスするために使用する関数です。理論的には do while ループで 10 ~ 20 回まで使用できますが、現在はループを削除したため、一度に 1 つの db クエリしか実行できません。これをさらに最適化できますか、それともトランザクションとコミットが適切に行われる方法ですか? また、 $db->rollBack() が実際に何をするのかわかりません。スタックオーバーフローで見ただけです

<?php
  function util_db_access($statement, $array) {
    $db = new PDO('mysql:host=localhost;dbname=db;charset=UTF8', 'user', 'pass');

    try {
      //echo "1";
      $db->beginTransaction();
      //echo "2";
      $stmt = $db->prepare($statement);
      //echo "3"; 
      if($stmt->execute($array)) {
        $db->commit();
        //echo "4";
        if($rows = $stmt->fetchAll(PDO::FETCH_ASSOC)) {
          //echo "5";
          if($stmt->rowCount() < 2) {
            $rows = $rows[0]; 
          }
          return $rows;
        } else {
          //echo "6.1";
          //$db->commit();
          return true;
        }
      } else {
        //echo "6.2";
        //$db->commit();
        return false;
      }
    } catch(PDOException $e) {
      $db->rollBack();
      //log, we are gonna keep a log eventually.. right?
      return -1;
    }
  }
?>
4

4 に答える 4

2

このことは非常に迅速に最適化できます。まず、すべての関数呼び出しでデータベースへの新しい接続を作成しています。PDO オブジェクトが範囲外になったときに接続が閉じられるかどうかはわかりませんが、それでも設計が悪いです。


アップデート

PDO オブジェクトが破棄されると、PHP はデータベースへの接続を閉じます。参照http://php.net/manual/en/pdo.connections.php

于 2013-03-13T18:28:21.033 に答える
1

$db->rollBack() はトランザクションをロールバックします。サーバーに不必要なオーバーヘッドが発生するため、トランザクションが何であるかがわからない場合は、それらを使用しても意味がありません。

commit() はクエリからのデータを永続的に書き込み、rollback() は beginTransaction() を呼び出した状態にすべてを元に戻します。

トランザクションは、複数の場所で同時に変更が発生することが重要な場合に使用されます。2 つのアカウント間の金銭のトランザクションを想像してみてください。単純な選択では、トランザクションはまったく必要ありません。

(try / catchの使い方にも懐疑的です)

しかし... dbサーバーで直接1つのクエリを実行すると、それも遅いですか? 各呼び出しの間にデータベース接続を開いたり閉じたりしますか? (もしそうなら-(はい)-しないでください)。http/db サーバー間のネットワーク関係は何ですか?

于 2013-03-13T18:29:03.030 に答える
1

プロファイラーを使用して、ボトルネックがどこにあるかを判断してみてください。xdebug にはボトルネックが含まれています。このコードの単純さを考えると、それはクエリ自体である可能性があります。mysql cli クライアントまたは MySQL Workbench を使用して、クエリをスタンドアロンで実行してみて、返されるタイミングを確認してください。クエリが遅い場合は、EXPLAIN と、MySQL マニュアルの豊富な最適化セクションを使用して、クエリを改善できます。

于 2013-03-13T18:16:49.160 に答える
0

あなたの関数を書き直し、無駄な部分を削除し、本質的な部分を追加せずにはいられません

function util_db_access($type, $statement, $array) {
    static $db;

    if (empty($db)) {
        $dsn = 'mysql:host=localhost;dbname=db;charset=UTF8';
        $opt = array(
            PDO::ATTR_ERRMODE            => PDO::ERRMODE_EXCEPTION,
            PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC
        );
        $db = new PDO($dsn, 'user', 'pass', $opt);
    }

    $stmt = $db->prepare($statement);
    $stmt->execute($array);
    if($type == 'all') {
        return $stmt->fetchAll();
    }
    if($type == 'row') {
        return $stmt->fetch();
    }
    if($type == 'one') {
        return $stmt->fetchColumn();
    }
    if($type == 'id') {
        return $db->lastInsertId();
    }
    if($type == 'numrows') {
        return $stmt->rowCount();
    }
}

ほとんどの場合、この新しいバージョンも遅延に悩まされることはありません

これで、遅延や不便なしにこの優れた機能を使用できます。

$user = util_db_access("row", "SELECT * FROM users WHERE id = ?", array($someId));
$id   = util_db_access("id", "INSERT INTO users SET name=?", array($name));

等々

ただ、そのための関数だけではかなり不便なので、早くクラス化してほしいです。いくつかのアイデアのソースとして、私のSafemysqlクラスを取り上げることができます。

于 2013-03-13T18:31:59.993 に答える