1

次のシナリオがあります。クライアントがサーバーにファイルをアップロードしています。ファイルはHibernateを介してOracleデータベースに保存されます。最近まで、ファイルをモデル化したエンティティにはbyte[]、Blobをモデル化するための配列属性がありました。InputStreamサーバーのRAMにファイル全体を入れたくないので、これをに変更しました。近い将来、より多くのユーザーがより大きなファイルをアップロードすることを期待しているため、RAMは確かに問題です。

私はいくつかのパフォーマンステストを行いましたが、これまでの結果は、バイト配列を挿入する場合と比較して、ストリーミングが約1.8倍遅いことを示しています。10回の反復で100MBのファイルを挿入した結果は次のとおりです。

Method       Mean Duration [ms]  SD [ms]
---------------------------------------
Byte Array   10733.0             264.0
Streaming    18089.0             913.0

クライアントとサーバー間の通信はSpringRMIを使用して行われ、バイナリデータ自体のストリーミングはRMIIOを使用して行われます。RMIIOを使用しているため、独自のBlobtypeを作成する必要がありました。この場合、クライアントからバイナリをアンラップして、blobのバイナリストリームにプッシュします。このためのコードは以下で見ることができます。

私がこれまでにしたこと:

  • 問題がどこにあるかを絞り込むために、RMIIOストリームをサービスメソッドでラップ解除してバイト配列に入れ、データベースに保存しました。そうすることで、バイト配列をずっと使用するのと同じパフォーマンスが得られます。したがって、パフォーマンスの低下はRMIIOパッケージによるものではなく、サーバーとデータベースの間のどこかによるものです。
  • バッファサイズを変更すると、パフォーマンスにわずかな影響があります

ストリームの挿入がバイト配列の挿入に比べて非常に遅い理由について、誰かが洞察を共有できますか?

私の構成:

  • 春3.1.1
  • RMIIO 2.0.0
  • Hibernate 3.6.10
  • Oracle 11.2.0.1.0
  • Oracle Driver for JDBC 10.2.0.5.0

バイト配列を持つ古いエンティティ(挿入が高速です):

@Entity
@Table(name = "MYBINARYOBJECT")
public class MyBinaryObject {

    @Id
    private Long id;

    @Lob
    private byte[] bytes;

}

入力ストリームを持つ新しいエンティティ(挿入が遅い):

@Entity
@Table(name = "MYBINARYSTREAMOBJECT")
public class MyBinaryStreamObject {

    @Id
    private Long id;

    @Type(type = "MyBlobType")
    private RemoteInputStream bytes;

}

カスタムBlobタイプ:

public class MyBlobType extends AbstractLobType {

    @Override
    protected Object nullSafeGetInternal(ResultSet rs, String[] names, Object owner, LobHandler lobHandler)
            throws SQLException, IOException, HibernateException {

        RemoteInputStreamServer server = new GZIPRemoteInputStream(lobHandler.getBlobAsBinaryStream(rs, names[0]));
        return server.export();
    }

    @Override
    protected void nullSafeSetInternal(PreparedStatement ps, int index, Object value, LobCreator lobCreator)
            throws SQLException, IOException, HibernateException {

        BufferedInputStream stream = null;
        try {
             ((RemoteInputStream) value).available();
             stream = new BufferedInputStream(
                    RemoteInputStreamClient.wrap((RemoteInputStream) value, RemoteRetry.NEVER), 16384);
             lobCreator.setBlobAsBinaryStream(ps, index, stream, -1);
        } catch (IllegalArgumentException e) {
            throw new MyStreamingException();
        }

    }
}
4

0 に答える 0