
No.4ベストアンサー
- 回答日時:
>御説明が足りずに失礼しました。
てっきり文脈から読み取って頂けるものとばかり思っておりました。いえ、こちらのほうこそ申し訳ないです。データベース周りのことについて、言葉をあまりに知らなさすぎて、回答者が質問者に余計な手間をかけさせてしまっているようでは話になりません。
とりあえず、色々あさっていたところ、
http://www.doctrine-project.org/blog/doctrine2-b …
こちらのエントリの一番したの「UPDATE」の箇所に、サポートしていない旨とその理由が掲載されていました。
Yahoo翻訳で、そこそこ読める翻訳が出来たのでそのまま転記します。
-------------------------------------
まず第一に、この構文は、mysqlとより新しいpostgresql版で支えられるだけです。第2に、AUTO_INCREMENTまたはSERIALとORMを使うことが識別子を物のアイデンティティ管理のために必要とするとき、そのようなマルチ挿入物ですべての発生する識別子をつかむ簡単な方法がありません。最後に、挿入パフォーマンスは、めったにORMのボトルネックでありません。大部分の状況のために十分に速いより、通常の挿入物は多くです、そして、あなたが本当に速い大きさ挿入物をしたいならば、マルチ挿入物はいずれにしろ最高の方法でありません、すなわち、Postgres COPYまたはMysql LOAD DATA INFILEは数桁より速いです。
--------------------------------------
結局ORMは複数のデータベースで実装されているSQL文を抽象化していることを考えると文自体のサポートの幅が少なければ、対応しないような方向のようですね。
Oracleでもマルチテーブルインサートとかあるようですし、SQL Server2008でもマルチインサートの構文がかけるようではありますが。
また、せっかくなので、CakePHPが独自で実装しているORMの、saveAllメソッドも試してみましたが、ログを見ると、複数のInsert文が流れているようでした。
やはり、SQL文を直接叩いて対応するのが近道なのではないかと思います。
MySQL/Postgres/SQL Server2008の間であれば、記法も同じようですし。
詳細な説明を求めておいて、ろくな回答できなくて、本当にすみません。
とんでもありません。丁寧な御回答、本当に感謝しています。
出来ないということが明確にわかっただけで収穫です。ありがとうございました。同時に自分の事前調査不足にも幾分反省しています。
このマニュアルではボトルネックではないと自信をもって断言していますが、1000件程度の同時Insertですらパフォーマンスに大きな差が出ます。また、LOAD DATA INFILE等ではあまりに柔軟性に欠けるので、話になりませんね。この自信はどこから来るのか…
とはいえ、マルチインサートに対応していないDBMSが存在することを考えると、確かに仕方ないのかもしれませんね。現行ORMの限界といったところでしょうか。とりあえずhogehoge78様のおかげでネイティブSQLが叩けることもわかったので、Doctrineのコードを読んで、saveメソッドをフックできるように改変してみたいと思います。
本当にありがとうございました。
No.3
- 回答日時:
となると、複数行Insertとはいったいどういうものをさしているのでしょう。
>配列フィールドを持つオブジェクトを永続化する際
コレについても良くわからないのですが、Array型のフィールドを有するテーブルに対して、Insertを行いたいということでしょうか。
もしそうであれば、MySQLはそもそもArray型をサポートしておりません。(一応Doctrineも見てみましたがArray型は正しくサポートしていないようです)
それとも、「複数行をまとめてInsertしたい」の複数行というのは、何か全然違う解釈のものでしたか?
この回答への補足
御説明が足りずに失礼しました。てっきり文脈から読み取って頂けるものとばかり思っておりました。
複数行Insertとは以下のようなものです。
http://dev.mysql.com/doc/refman/5.1/ja/insert.htmlより
==============================
VALUES 構文を利用する INSERT ステートメントは複数行を挿入する事ができます。これをする為には、それぞれが括弧で囲まれカンマで区切られている、カラム値の複数リストを含んでください。例:
INSERT INTO tbl_name (a,b,c) VALUES(1,2,3),(4,5,6),(7,8,9);
==============================
これにより、(1,2,3)と(4,5,6)と(7,8,9)の3行を挿入するのに必要なSQL発行回数が1回で済みます。SQL発行回数の減少はディスクへのランダムアクセス回数の減少に繋がりますので、結果として全体のパフォーマンスが向上します。
>配列フィールドを持つオブジェクトを永続化する際
クラスAの配列をフィールドとして持つクラスBのsave()メソッドを叩いた時、ということです。
この際、大概のORMでは(もしくは適切な設定によって)BのインスタンスのフィールドであるAの配列の永続化も自動的に行われますが、Doctrineの場合ですと要素ごとに1件のSQLが発行されてしまいます。
上記の例で言えば
INSERT INTO tbl_name (a,b,c) VALUES(1,2,3);
INSERT INTO tbl_name (a,b,c) VALUES(4,5,6);
INSERT INTO tbl_name (a,b,c) VALUES(7,8,9);
ということですね。
※「配列の永続化」とは、Array型?を用いた永続化ではなく、外部キーによって結合されているテーブルへの永続化を指しています。
この複数件のSQLを、先程の複数行同時InsertSQLに自動的にパックするような機能や設定方法はないか?もしくはクラスBの特定のフィールドだけ永続化処理をハックできるような方法はないか?というのが本質門の主旨でした。
宜しくお願い致します。
No.2
- 回答日時:
となると、ある程度コストがかかってしまいますが、
<?php
//一回目
$insert = new Hoge();
$insert->name = 'aaa';
$insert->date = time();
$insert->save();
//二回目
$insert = new Hoge(); //ここでインスタンス作り直し
$insert->name = 'bbb';
$insert->date = time();
$insert->save();
?>
と、一行インサートを行うたびにインスタンスを作り直すという作業は必要かもしれませんね。
実際マニュアルでも2回インサート処理をしているコードのサンプルがありましたが、そのようにしていたようです。
No.1
- 回答日時:
Doctrine使ったことないですが、
多少複雑なことを行うのであれば、他のORマッパーでもそうですが、直接SQLを叩いたほうがよさそうですが、いかがでしょうか。
Doctrine_Managerのconnectionメソッドが返すDoctrine_Connectionクラスには、prepareメソッドがありますので、
$stmt = $conn->prepare("INSERT INTO hoge (a, b, c) VALUES (?, ?, ?)");
$stmt->execute(array(1, 2, 3));
といった感じで。
御回答ありがとうございます。
やはりネイティブSQLを叩けるインターフェースがあったんですね。調査不足でした、すみません。
しかしDoctorine_Record::saveメソッドで安直に永続化できないとなると、ORMを使う意味がどんどん薄れていきますね…コレクション周りを工夫すれば割と簡単に実現できそうなものですが。。(自分で実装する気は起きない)
複数行Insertを実現できるPHPのORMをもし御存知でしたら、御教示下さい。
宜しくお願い致します。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
file_existsでファイル名の部分...
-
PHPのカッコ[ ]の使い方について
-
PHPにてクラスを配列にすること...
-
foreachのなかで次のキーを参照...
-
漢字のソートについて
-
postgresql関数をつかったレコ...
-
PHPでcsvファイルデータ内の一...
-
multiple属性のPOSTを配列で受...
-
PHPでテキストファイルの一部を...
-
C言語の配列をPush(追加)する...
-
【PHP】配列のキー名の修正は可...
-
プルダウンメニューにDBの内容...
-
CArrayのソート
-
多次元配列をソートする綺麗な...
-
C言語 最大値と最小値を求めて...
-
PHPで連想配列のプルダウンメニ...
-
マッチング処理(1:N)
-
【PHP】チェックボックスの必須...
-
FortranのOPEN文
-
POSTで渡されるデータの数がわ...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
String だと「 ByRef引数の型が...
-
$_SESSIONに二次元配列を使える...
-
配列をループでたくさん宣言し...
-
ネストが深い時のforeachはどう...
-
配列を回すとき、最後の要素だ...
-
file_existsでファイル名の部分...
-
PHPにてクラスを配列にすること...
-
foreachのなかで次のキーを参照...
-
postgresql関数をつかったレコ...
-
【Smarty】foreach関数やsectio...
-
漢字のソートについて
-
チェックボックス複数選択 mys...
-
Smartyについて
-
PHP掲示板で新着順に表示させた...
-
PHP 多次元配列変数のデータ受...
-
チェックボックスが複数選択で...
-
PHPのカッコ[ ]の使い方について
-
sortableで並べ替えてDBに保...
-
【PHP】配列内のある値以上をカ...
-
SQL文の実行結果を変数で受けて...
おすすめ情報