web-dev-qa-db-ja.com

MySQL-Base64とBLOB

簡単にするために、Instagramのようなモバイルアプリを開発しているとします。ユーザーはサーバーから画像をダウンロードし、自分の画像をアップロードできます。現在、サーバーはすべての画像(実際には小さなサムネイルのみ)をBLOBとしてMySQLデータベースに保存しています。画像を転送する最も一般的な方法は、Base64エンコーディングを使用することです。

  1. サーバーはすべての画像をBLOBとして保存します。画像をアップロードするために、クライアントは画像をBase64文字列にエンコードし、サーバーに送信します。サーバーは画像のBACKをバイナリ形式にデコードし、BLOBとしてデータベースに保存します。クライアントが画像を要求すると、サーバーはその画像をBase64文字列として再エンコードし、クライアントに送信します。クライアントはそれをバイナリにデコードして表示します。
  2. サーバーはすべての画像をBase64文字列として保存します。画像をアップロードするために、クライアントはそれをBase64文字列にエンコードし、サーバーに送信します。サーバーはエンコードもデコードも行わず、データベースに文字列を格納するだけです。クライアントが画像を要求すると、Base64文字列がクライアントに返され、クライアントはそれをデコードして表示します。

明らかに、オプション#1はサーバー上でかなり多くの処理を必要とします。画像はすべてのリクエストでエンコード/デコードされる必要があるためです。これにより、オプション#2に傾くようになりますが、MySQLにBase64文字列を保存することは、イメージを直接BLOBとして保存するよりもはるかに効率が悪く、一般的には推奨されないことがいくつかの研究で示唆されています。

私は確かにこの状況に遭遇する最初の人ではないので、誰かがこの作業を行うための最良の方法についての提案を持っていますか?

23
Hundley

JSONはutf8を想定しているため、何らかの方法でエンコードされない限り、画像との互換性はありません。

Base64は、バイナリ(BLOB)のほぼ正確に8/6倍の大きさです。それは簡単に手頃な価格であると主張することができます。 3000 bytesは約4000 bytesになります。

全員すべき任意の8ビットコードを受け入れることができますが、誰もが受け入れるわけではありません。 Base-64は、8ビットデータを処理する必要がないための最も単純で全体的な最善の妥協案です。

これらは「小さい」ため、ファイルではなくテーブルに格納します。ただし、別のテーブルにそれらを格納し、必要に応じて適切なJOINを使用してidを格納します。これにより、BLOBをステップオーバーしないため、イメージを必要としないクエリをより高速に実行できます。

技術的には、TEXT CHARACTER SET ascii COLLATE ascii_binでも可能ですが、BLOBを指定すると、列に実際に使用可能なテキストがないことが明確になります。

8
Rick James

なぜワイヤー上で画像をbase64エンコードするのですか?あなたは間違った仮定から始めていると思います。

1
Julian Reschke

DBサーバーがバイナリデータを常にネイティブ形式で保持する必要がない理由はわかりません。したがって、BLOBを使用します。 (ただし、データをBase64文字列で格納した場合でも、IOの影響がより大きくなるため、エンコード/デコードのパフォーマンスについて心配する必要はありません。)

クライアントがbase64でデータを送信する必要がある理由がわかりません。単純なHTTP呼び出しを使用して単に「ストリーミング」しないのはなぜですか?

0