俺流テキストデータベース #4 スピードアップ呼び出し術

2018年11月20日

PHP テクノロジー プログラミング 特集

プログラムをやり始めた頃は「Hello World」だけで感動できるモチベーションがありますが、人は物事に慣れてくる生き物なため、次第に同じことだけでは感動できなくなり、さらに上位の感動を求めるようになります。 プログラムの基本はif文とfor文だけで十分ですが、次には「効率」を追求するための「アルゴリズム」に行き着きます。 より質の高いプログラムを作り続けられれば、人は常に満足したコーディングライフを送れるという事がわかります。 前回行なった保存したデータベースの読み込み処理ですが、基本的にはPHPプラットフォームで展開されているので、PHP自体の処理を超えられないというボトルネッックが存在してしまいます。 今回は、LinuxOSのベースにもなっているShellスクリプトを使ってデータソースを読み解く手段をサンプルを使って解説します。

サンプルソースコードと解説

<?php namespace textDatabase; /** * 保存したデータを読み込む 第2方式 */ class dataReadShell{ // strstring convert public static function stringEncode($string){ $string = str_replace("&" , "&#38;" , $string); $string = str_replace("," , "&#44;" , $string); return $string; } public static function stringDecode($string){ $string = str_replace("&#44;" , "," , $string); $string = str_replace("&#38;" , "&" , $string); return $string; } public static function arrayDecode($arr){ foreach($arr as $key => $value){ $arr[$key] = self::stringDecode($value); } return $arr; } // csv public static function read_csv($filename , $name){ unset($res); exec("awk -F, '{if($1==\"".$name."\"){print $0}}' " .$filename.".csv" , $res); $results = array(); for($i=0; $i<count($res); $i++){ $cells = explode(",",$res[$i]); for($j=0; $j<count($cells); $j++){ $cells[$j] = self::stringDecode($cells[$j]); } array_push($results , $cells); } return $results; } // json multi public static function read_json_multi($filename , $name){ unset($res); exec("cat ". $filename .".multi.json | tr '\\n' ',' | sed -e 's/,$//' | echo '[' $(cat) ']' | jq -r \". | map(select(.name == \\\"". $name ."\\\"))\" " , $res); return json_decode(join("",$res) , true); } } $ php read2.php Array ( [0] => Array ( [0] => apple [1] => 10 [2] => 1,200 [3] => ) ) Array ( [0] => Array ( [name] => apple [count] => 10 [price] => 1,200 ) ) 前回使用した1ファイルに1jsonを保存する方式は、今回は使いません。 PHPで読み込んだtrxtデータをjson_decodeするだけなので、前回と同じコードになります。 今回はcsv読み込みにはawk、json-multi形式にはjqコマンドを使ってphpへの取り込みを実現しています。 phpのexecコマンドを使う事で、ワンラインshellコマンドとして値を受け取れるので、前回まで、一旦全てのテキストデータをphpでメモリ保存して、それを処理していましたが、shellコマンドを使ってのテキストファイルからのデータ読み込みは、phpのメモリを使うよりはるかに高速に行う事ができるので、かなりの速度改善が見込めます。 もちろん、shellスクリプトも、awkスクリプトも、jqコマンドも、それぞれしっかり学習する必要はありますが、まずは今回のソースコードを少しずつ変えて使って見てもある程度使える程度には学習できるはずです。 ちなみに、csv形式をcatコマンド+cutコマンド+grepコマンドで、任意セル箇所の文字列を判定する事は可能ですが、判定結果後に、対象のレコードを全てPHPに受け渡したかったので、判定から結果の形式がコントロールできるawkコマンドを使って見ました。 awk記事も以前に書いたので、よかったら参考までに見てくださいませ。 awkメモ書き jqコマンドの方は、かなりパイプで繋いでいる事が見てわかると思いますが、「cat + tr + sed + echo + jq」と言う具合に、json-multi形式を一旦json形式に整形してからjqに受け渡しています。 jqコマンドもずっと前に記事投稿しているのでこちらも気になる人はどうぞ。 JSONファイルをコマンドで扱える「jq」を学習してみる #1「初期設定」

いろいろ検討事項

前回の読み込み処理から、今回の読み込み処理に切り替える事で、速度改善が見込めますが、その際にデータの保持形式で、price部分が、3桁ごとにカンマ(,)で区切る文字列をそのまま保存しているので、数値ではなく、文字列登録になっています。 データ取得の段階で、数字はすべてnumericで登録すると、jqコマンドやawkコマンドでの四則演算など簡単な値集計を行う事が可能になります。 データベースのカラム設計と同じような思考で設計するといいでしょう。 さらに読み込んだ後で、PHPで整形するよりも、各種コマンドで結果を直接取得したい場合は、それぞれの言語ライブラリを作っておくと言うてもあります。 次回はそうしたやり方を紹介したいと思います。

このブログを検索

ごあいさつ

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