この記事で紹介するのはPHP上であるデータを可逆圧縮する方法と例です。通信内容のログなど何かしら大きなデータをデータベースに格納する時に特に役に立つ方法です。
使うのはZlib関数のgzcompress, gzencode, gzdeflateです。これらはgzip圧縮の様な(gzencodeはgzip圧縮そのもの)圧縮をします。それぞれ対応する解凍関数があり、PHP上(メモリ上)のみで完結できます。
PHP: Zlib – Manual
PHP: gzcompress – Manual
PHP: gzencode – Manual
PHP: gzdeflate – Manual
使用例は次です。
<?php /** @see http://sandbox.onlinephpfunctions.com/code/b61e09f21ce9ec4f0c03cff5b625845c2aecfcad */ // $data = random_str(1e6); // 英数字ランダム // $data = str_repeat('a',1e7); // 同じ文字を繰り返し $data = serialize(range(1, 1000)); // 規則的な文字列 echo 'strlen($data) : ' . strlen($data) . "\n\n"; $gzc = gzcompress($data); echo 'strlen(gzcompress($data)) : ' . strlen($gzc) . "\n"; echo 'strlen(gzcompress($data, 9)) : ' . strlen(gzcompress($data, 9)) . "\n"; echo 'gzuncompress($gzc) === $data : ' . (gzuncompress($gzc) === $data ? 'true' : 'false') . "\n\n"; $gze = gzencode($data); echo 'strlen(gzencode($data)) : ' . strlen($gze) . "\n"; echo 'strlen(gzencode($data, 9)) : ' . strlen(gzencode($data, 9)) . "\n"; echo 'gzdecode($gze) === $data : ' . (gzdecode($gze) === $data ? 'true' : 'false') . "\n\n"; $gzd = gzdeflate($data); echo 'strlen(gzdeflate($data)) : ' . strlen($gzd) . "\n"; echo 'strlen(gzdeflate($data, 9)) : ' . strlen(gzdeflate($data, 9)) . "\n"; echo 'gzinflate($gze) === $data : ' . (gzinflate($gzd) === $data ? 'true' : 'false') . "\n"; function random_str($length) { $bytes = random_bytes($length); return substr(str_replace(['/', '+', '='], '', base64_encode($bytes)), 0, $length); } // strlen($data) : 11792 // // strlen(gzcompress($data)) : 1395 // strlen(gzcompress($data, 9)) : 1391 // gzuncompress($gzc) === $data : true // // strlen(gzencode($data)) : 1407 // strlen(gzencode($data, 9)) : 1403 // gzdecode($gze) === $data : true // // strlen(gzdeflate($data)) : 1389 // strlen(gzdeflate($data, 9)) : 1385 // gzinflate($gze) === $data : true
第二引数は圧縮レベルです。例では1/10以下になる圧縮率で非常に強力な動作をしていますがこれは元データの規則性に左右されます。圧縮率の振れ幅は英数字完全ランダムでは3/4程度、同じ文字がひたすら続くならば1/1000程度と大きいです。
実行速度は格別遅いような感覚もなく自然に使えます。データベースに保存する場合、直接人間がSQLを叩いてログを読めなくなりますが、ディスクをあまり占有しない上カラムで指定されたデータサイズより大きなデータを格納しようとする問題を起きにくくできます。