5

DECIMALデフォルトの精度設定で列を作成すると、H2 Web コンソールでこの列が として定義されDECIMAL(65535, 32767)、コマンド「show columns from ...」が表示されますDECIMAL(65535)

H2 の Decimal データ型はBigDecimal(H2 のドキュメントから) にマップされていますが、H2 がそれをどのように処理するかはわかりません。

より低い精度を使用すると、パフォーマンスが向上しますか?

4

2 に答える 2

6

DECIMALH2のデータ型について詳しく知るにorg.h2.value.ValueDecimalは、h2-x.y.z.jar.

よく見ると、デフォルト値はあなたが述べたとおりです。

/** The default precision for a decimal value. */
static final int DEFAULT_PRECISION = 65535;
/** The default scale for a decimal value.     */
static final int DEFAULT_SCALE = 32767;

で詳しく見るValueDecimal:

private final BigDecimal value;

org.h2.store.Data:

public Value readValue() {
    ...
    case Value.DECIMAL: {
        int scale = readVarInt();
        int len = readVarInt();
        byte[] buff = DataUtils.newBytes(len);
        read(buff, 0, len);
        BigInteger b = new BigInteger(buff);
        return ValueDecimal.get(new BigDecimal(b, scale));
    }

DECIMALa は aにすぎないことがわかりますBigDecimal。つまり、直面するすべてのパフォーマンスの問題、直面するjava.math.BigDecimalことになりますDECIMAL

本当に興味がある場合は、クラスをさらに学習して、精度/スケールが果たす正確な役割を確認できます。

DECIMALドキュメントにアクセスすると、データ型とパフォーマンスに関する H2 の発言は次のとおりです。

DECIMAL/型はand型よりも遅く、NUMERICより多くのストレージを必要とします。REALDOUBLE

だから彼らはそれが事実だと言います。

しかし、パフォーマンスについて話しているので、本題に入っていくつかのテストを行うことができます。テスト クラスのコードは以下のとおりです。出力/結果を見てみましょう。

TYPE              INSERT time    COUNT() time   .db Size (kb)  
DECIMAL(20,2)     6.978          0.488          27958.0        
DECIMAL(100,2)    4.879          0.407          25648.0        
DECIMAL(100,80)   8.794          0.868          90818.0        
DECIMAL(60000,2)  4.388          0.4            25104.0        
DECIMAL(1000,900) 112.905        6.549          1016534.0      
REAL              5.938          0.318          22608.0        
DOUBLE            6.985          0.416          25088.0    

ご覧のとおり、精度が変化しても、時間やストレージ サイズに目立った変化はありません (精度20には、おおよそ ! と同じくらいの時間/サイズが必要60000です)。

問題は、スケールを変更するときです。これはあなたが心配すべきことです。ご覧のとおり、時間DECIMAL(100,2)DECIMAL(100,80)ストレージの両方が大幅に増加しています。

DECIMAL(1000,900)まったく同じ値を格納するために1 ギガバイト(!!!)以上かかります。

最後に、上記のテストでは、REALandDOUBLEよりもはるかに優れているようには見えませんDECIMAL(さらに悪く見える場合もあります)。ただし、挿入される行数 (forテスト メソッドのループ) を変更してみてください。数値が大きいほど、応答が良くなるようです。

*DECIMAL(20,2)他のものよりも遅い/大きいようです。それは本当ではありません。実際、最初に実行することを選択したものは、わずかに遅く/大きくなります。図に行く...

public class Main {
    public static void main(String[] a) throws Exception {
        Class.forName("org.h2.Driver");
        System.out.format("%-18s%-15s%-15s%-15s", "TYPE", "INSERT time", "COUNT() time", ".db Size (kb)");
        System.out.println();
        testPerformance("TEST_DECIMAL_20_2",     "DECIMAL(20,2)");
        testPerformance("TEST_DECIMAL_100_2",    "DECIMAL(100,2)");
        testPerformance("TEST_DECIMAL_100_80",   "DECIMAL(100,80)");
        testPerformance("TEST_DECIMAL_60000_2",  "DECIMAL(60000,2)");
        testPerformance("TEST_DECIMAL_1000_900", "DECIMAL(1000,900)");
        testPerformance("TEST_REAL",             "REAL");
        testPerformance("TEST_DOUBLE",           "DOUBLE"); 
    }

    private static void testPerformance(String dbName, String type) throws SQLException {
        System.out.format("%-18s", type);
        Connection conn = DriverManager.getConnection("jdbc:h2:" + dbName, "sa", "");
        conn.createStatement().execute("DROP TABLE IF EXISTS TEST;");
        conn.createStatement().execute("CREATE TABLE TEST (DECTEST " + type +" )");
        long insertStartTime = System.currentTimeMillis();
        for (int i = 0; i < 1000000; i++) {
            conn.createStatement().execute("INSERT INTO TEST (DECTEST) VALUES (12345678901234.45)");    
        }
        double insertTime = ((double)(System.currentTimeMillis()-insertStartTime))/1000;
        System.out.format("%-15s", insertTime+"");
        long countStartTime = System.currentTimeMillis();
        conn.createStatement().executeQuery("select COUNT(DECTEST) from TEST");
        double countTime = ((double)(System.currentTimeMillis()-countStartTime))/1000;
        System.out.format("%-15s", countTime+"");
        conn.close();
        double fileSize = (double)new File(dbName+".h2.db").length() / 1024;
        System.out.format("%-15s", fileSize+"");
        System.out.println();
    }
}
于 2013-04-30T04:16:57.117 に答える
3

の精度と位取りはDECIMAL、H2 ではオプションです。精度/スケールを指定せずに列を作成すると、パフォーマンスは影響を受けず、ストレージも影響を受けず、任意の値を挿入して同じ値を取得できます。

create table test(data decimal);
insert into test values(1.345);
select * from test;
> 1.345
于 2013-04-30T05:01:26.270 に答える