2016-02-26 6 views
7

任意のDB結果(つまり、必ずしもすべてのテーブルxからのものではない)から適切なPHP型の結果に自動変換するものを書き込もうとしています。私はPDOの抽象化を知っていた前PDO(getColumnMeta is/slow /)を使用して列の型を取得

は、私は、以前、

class Statement extends PDOStatement { 
    protected $pdo; 
    protected $transformer; 

    protected function __construct(PDO $pdo) { 
     $this->pdo = $pdo; 
     $this->transformer = $pdo->getTransformer(); 
    } 

    public function fetchAll() { 
     $results = parent::fetchAll(PDO::FETCH_ASSOC); 

     if ($this->getTransformer()) $results = $this->completeResults($results); 

     return $results; 
    } 

    private function completeResults(array $results = []) { 
     if ($results == null || count($results) == 0) return null; 
     if ($results[0] == false || !is_array($results[0])) return null; 

     $index = 0; 
     $typeMap = []; 

     foreach ($results[0] as $column => $result) { 
      $meta = $this->getColumnMeta($index); // this is very painful 
      $typeMap[$column] = $meta['native_type']; 
      $index++; 
     } 

     $transformer = $this->getTransformer(); 
     foreach ($results as $index => &$result) { 
      array_walk($result, function(&$value, $key) use ($typeMap, $transformer) { 
       $type = $typeMap[$key]; 
       $value = $transformer->transformToPhpValue($value, $type); 
      }); 
     } 

     return $results; 
    } 
} 

をPDOStatementにクラスを拡張し、私は(私の特定の場合には)標準PG _...()メソッドを使用していました。 pg_field_type($resource, $column);を使って、私は列の型を取り出すことができました、そして、それは比較的速かったです。

今、新しい(私にとって)PDOメソッドを使用します。私は7つの連続したクエリを、私は変換を行う私のコードの一部をコメントアウトし、実行した場合:それで

time to complete: 9.5367431640625E-7 seconds 
time to complete: 1.1920928955078E-6 seconds 
time to complete: 9.5367431640625E-7 seconds 
time to complete: 0 seconds 
time to complete: 9.5367431640625E-7 seconds 
time to complete: 0 seconds 
time to complete: 0 seconds 

が有効になって:/非常識/だ

time to complete: 0.5777850151062 seconds 
time to complete: 0.49124097824097 seconds 
time to complete: 0.28375911712646 seconds 
time to complete: 0.5946729183197 seconds 
time to complete: 0.42177200317383 seconds 
time to complete: 5.0067901611328E-6 seconds 
time to complete: 0.42121982574463 seconds 

私はそれが私のPostgresのログを見て、一つ一つによって列情報1をフェッチだ伝えることができます:

LOG: statement: SELECT TYPNAME FROM PG_TYPE WHERE OID=1114 
LOG: statement: SELECT TYPNAME FROM PG_TYPE WHERE OID=1114 
LOG: statement: SELECT TYPNAME FROM PG_TYPE WHERE OID=25 
... like 30 more of these ... 
LOG: statement: SELECT TYPNAME FROM PG_TYPE WHERE OID=25 
LOG: statement: SELECT TYPNAME FROM PG_TYPE WHERE OID=23 
LOG: statement: SELECT TYPNAME FROM PG_TYPE WHERE OID=23 
LOG: statement: SELECT TYPNAME FROM PG_TYPE WHERE OID=23 

クエリが

SELECT 
    p.modified_at, ... ~ 30 fields ..., r.level AS id_level 
FROM table_p AS p 
LEFT JOIN table_a AS a ON (p.owner = a.id) 
LEFT JOIN table_a0 AS a0 ON (p.reporter = a0.id) 
LEFT JOIN table_r AS r ON (p.id = r.id) 
WHERE (p.id = 1) 

からわずかSELECT * FROM table_a AS a;

に複雑に及びます

質問:です:これを行うには良い方法がありますか?私のコードの速度に影響を与えずにこれを行うことができる方法はありますか? 7つのクエリは、要求ごとに実行される連続したクエリのローエンドにあります。そのため、私は対処したいことがあります。

+1

私は今のところ、まだ実験的なので、phpで使う方がよいと思います。軽い年が早いでしょう。 – cpugourou

+0

プロジェクトにPostgresqlだけを使用する予定の場合は、PDOの代わりにネイティブpgsqlライブラリを使用することを強くお勧めします。 PDOが遅くなり、機能が少なくなります。あなたのタイプの問題の答えはhttp://stackoverflow.com/questions/31643297/pg-query-result-contains-strings-instead-of-integer-numeric/31740990#31740990 – greg

+0

@ええ、これは私が使っていたものです前。残念ながら、それはPDOがパッケージ化された多くの機能を書くことを意味しました... –

答えて

1

まず、PDOStatement::getColumnMeta()実験ですので、非常に注意してください(phot/pdoバージョンのアップデートでこれをチェックするよう自動テストを設定してください)。

メタデータを取り出すの速度に関しては、私はいくつかのテストを実行してきましたし、それがSELECT TYPNAME FROM PG_TYPE WHERE OID=%クエリが速く燃えるを実行していることが判明:、

explain analyze SELECT TYPNAME FROM PG_TYPE WHERE OID=25; 
                 QUERY PLAN               
---------------------------------------------------------------------------------------------------------------------------- 
Index Scan using pg_type_oid_index on pg_type (cost=0.27..8.29 rows=1 width=64) (actual time=0.051..0.055 rows=1 loops=1) 
    Index Cond: (oid = 25::oid) 
Planning time: 0.165 ms 
Execution time: 0.100 ms 
(4 rows) 

explain analyze SELECT TYPNAME FROM PG_TYPE WHERE OID=1114; 
                 QUERY PLAN               
---------------------------------------------------------------------------------------------------------------------------- 
Index Scan using pg_type_oid_index on pg_type (cost=0.27..8.29 rows=1 width=64) (actual time=0.083..0.085 rows=1 loops=1) 
    Index Cond: (oid = 1114::oid) 
Planning time: 0.192 ms 
Execution time: 0.139 ms 
(4 rows) 

explain analyze SELECT TYPNAME FROM PG_TYPE WHERE OID=600; 
                 QUERY PLAN               
---------------------------------------------------------------------------------------------------------------------------- 
Index Scan using pg_type_oid_index on pg_type (cost=0.27..8.29 rows=1 width=64) (actual time=0.063..0.064 rows=1 loops=1) 
    Index Cond: (oid = 600::oid) 
Planning time: 0.261 ms 
Execution time: 0.125 ms 
(4 rows) 

これは、そのデータを選択するためのPGのための約0.0001秒ですこれらの30個を加算することさえも、0.5秒またはそれに類するものではない。

ご質問pg_typeのクエリでサーバーにexplain analyzeを実行し、そのタイミングを確認することをおすすめします。

DBに永続的な接続を使用していないと、メタデータの呼び出しに時間がかかります。

関連する問題