[PHP] MySQLのAUTO_INCREMENTをJSONデータベースで実現するには?

2019年7月30日

テクノロジー プログラミング

SQLにおける自動採番は、非常に便利なのですが、テキストデータべースやJSONデータで同じように自動採番をする方法を考えてみました。 この方法は、簡易にデータ構築をしたい場合や、SQLトランザクション問題を起こしたくない場合などにご使用ください。 JSONデータベースについてよくわからない人は、は以下の記事を参照してください。 俺流テキストデータベース #2 書き込みサンプルプログラム

データ保存は、INSERT(追加)とUPDATE(更新)

これまでのテキストデータベースは全て追記方式で行っていたので、限りなく負荷を抑えることができ、同時書き込みなどもさほど気にせずに行うことが出来ましたが、オートインクリメントによる自動採番をする場合は、データ更新の概念において、IDを参照する必要があります。 普通にオートインクリメントを実現させようとすると、採番するたびに採番用のデータ(数値)をインクリメントさせていき、その数値をIDとして使うという仕様を考えがちですが、このやり方だと全く高速化することができません。 今回の仕様を簡単に説明すると、自動採番は、テキストファイルの改行コードをそのまま使うようにして、データ更新として同じIDを複数書き込む時には、改行コードをID(PRIMARY-KEY)として、書き込むようにするだけで、まるで自動採番をしているかのような動作になります。 その際に重要なのが、基本的操作は全てテキストに対してデータ追加なのですが、データの新規登録をするのか、既存データの更新作業をするのかを分けた作業で行う必要があります。 この点はSQLと同じ手順と考えるといいでしょう。 SQLを高速にしているポイントももしかしたら同じ仕様なのかもしれませんね・・・

データサンプル

JSONデータのサンプルです。 {"name":"上田","memo":"次郎"} {"name":"山田","memo":"奈緒子"}

データ追加

以下のデータを新規追加させる場合は、単純に追記をします。 {"name":"矢部","memo":"謙三"} PHPでは下記のように登録します。 <?php $data = array( "name" => "矢部", "memo" => "謙三" ); $json = json_encode($data , JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); file_put_contents("sample.json" , $json , FILE_APPEND);

データ更新

次に登録済みの2行目のデータを更新する場合は、primary-keyとする"id"キーに行数をいれてデータを追記します。 {"id":"2", "name":"仲間","memo":"由紀恵"} 上記とさほど変わらないですが、idがついてるところがポイントです。 <?php $data = array( "id" => 2, "name" => "仲間", "memo" => "由紀恵" ); $json = json_encode($data , JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); file_put_contents("sample.json" , $json , FILE_APPEND);

今現在のjsonデータ

上記の追記と更新が反映されたデータは以下のようになります。 {"name":"上田","memo":"次郎"} {"name":"山田","memo":"奈緒子"} {"name":"矢部","memo":"謙三"} {"id":"2", "name":"仲間","memo":"由紀恵"}

データ読み込み

そして最も重要なのが、jsonデータの読み込み方法です。 現在のjsonデータを以下のPHPで読み込む事で、最新データが表示されることを確認します。 <?php $fileDatas = file_get_contents("sample.json"); $lineDatas = explode("\n" , $fileDatas); $newDatas = array(); $flg = array(); for($i=count($lineDatas)-1; $i>=0; $i--){ // 空行を省く if(!$lineDatas[$i]){continue;} // 行データをjson変換 $jsonData = json_decode($lineDatas[$i] , true); // idが無い場合はAUTO-INCREMENTとして行番号を当てはめる if(!isset($jsonData["id"]) || $jsonData["id"] === null){ $jsonData["id"] = $i+1; } // 重複するデータを省く if(isset($jsonData["flg"]) && isset($flg[$jsonData["id"]])){continue;} // 重複データ用フラグセット $flg[$jsonData["id"]] = true; // 論理削除フラグ対応 if($jsonData["flg"] == 1){continue;} // 対象データとして登録 array_unshift($newDatas , $jsonData); } print_r($newDatas); $ php load.php Array ( [0] => Array ( [name] => 上田 [memo] => 次郎 [id] => 1 ) [1] => Array ( [name] => 矢部 [memo] => 謙三 [id] => 3 ) [2] => Array ( [id] => 2 [name] => 仲間 [memo] => 由紀恵 ) ) 一覧データで内容が更新されていることが確認できます。

注意すべきは大容量データ対応

オートインクリメントのやり方がわかったのですが、単純なデータであれば、このままソースコードをコピペして使えばいいのですが、大容量データの場合は、少し手を加える必要があります。 SQLではINDEXをセットするという概念がありますが、テキストデータの場合にもINDEXという思考はそのまま当てはめられます。 今回は細かく説明しませんが、INDEXのセットされたカラムデータのカラム値をjsonファイル名として、別々に保存する事で、大容量対応することが可能になります。 書き込み時ではさほど問題は無いのですが、読み込み(load)時にデータ検索スピードが犠牲になるので、INDEX対応が重要になるケースも少なくないでしょう。 この辺はデータ設計思想の知識が必要なので、詳細は割愛しますね。 とりあえず、今回の方法を使うことでプログラム構築作業が大幅に削減できる事が多いので、モックアップ作成などにてお使いください。

このブログを検索

ごあいさつ

このWebサイトは、独自思考で我が道を行くユゲタの少し尖った思考のTechブログです。 毎日興味がどんどん切り替わるので、テーマはマルチになっています。 もしかしたらアイデアに困っている人の助けになるかもしれません。