2011-08-02 75 views
1

テストケース:H2最適化select文/シャットダウンデフラグ

drop table master; 
create table master(id int primary key, fk1 int, fk2 int, fk3 int, dataS varchar(255), data1 int, data2 int, data3 int, data4 int,data5 int,data6 int,data7 int,data8 int,data9 int,b1 boolean,b2 boolean,b3 boolean,b4 boolean,b5 boolean,b6 boolean,b7 boolean,b8 boolean,b9 boolean,b10 boolean,b11 boolean,b12 boolean,b13 boolean,b14 boolean,b15 boolean,b16 boolean,b17 boolean,b18 boolean,b19 boolean,b20 boolean,b21 boolean,b22 boolean,b23 boolean,b24 boolean,b25 boolean,b26 boolean,b27 boolean,b28 boolean,b29 boolean,b30 boolean,b31 boolean,b32 boolean,b33 boolean,b34 boolean,b35 boolean,b36 boolean,b37 boolean,b38 boolean,b39 boolean,b40 boolean,b41 boolean,b42 boolean,b43 boolean,b44 boolean,b45 boolean,b46 boolean,b47 boolean,b48 boolean,b49 boolean,b50 boolean); 

create index idx_comp on master(fk1,fk2,fk3); 
@loop 5000000 insert into master values(?, mod(?,100), mod(?,5), ?,'Hello World Hello World Hello World',?, ?, ?,?, ?, ?, ?, ?, ?,true,true,true,true,true,true,false,false,false,true,true,true,true,true,true,true,false,false,false,true,true,true,true,true,true,true,false,false,false,true,true,true,true,true,true,true,false,false,false,true,true,true,true,true,true,true,false,false,false,true); 

1. select文次は30秒を要します。応答時間を最適化する方法はありますか?

SELECT count(*), SUM(CONVERT(b1,INT)) ,SUM(CONVERT(b2,INT)),SUM(CONVERT(b3,INT)),SUM(CONVERT(b4,INT)),SUM(CONVERT(b5,INT)),SUM(CONVERT(b6,INT)),SUM(CONVERT(b7,INT)),SUM(CONVERT(b8,INT)),SUM(CONVERT(b9,INT)),SUM(CONVERT(b10,INT)),SUM(CONVERT(b11,INT)),SUM(CONVERT(b12,INT)),SUM(CONVERT(b13,INT)),SUM(CONVERT(b14,INT)),SUM(CONVERT(b15,INT)),SUM(CONVERT(b16,INT)) 
FROM master 
WHERE fk1=53 AND fk2=3 

2.シャットダウンデフラグを試みました。しかし、この声明は私のテストケースで約40分かかった。シャットダウンのデフラグ後、選択には最大15秒かかります。文をもう一度実行すると、1秒以下かかります。サーバを停止して起動しても、文は約1秒かかります。 H2に永続キャッシュがありますか?

インフラ:Webブラウザー< - > H2コンソールサーバ< - > H2 DB:1.3.158

+0

クエリのスキャンの行数はいくつですか? 50000(不明)のようです。 –

+0

PUBLIC.MASTER /* PUBLIC.IDX_COMP FROM COUNT(*)、 SUM(CONVERT(B1、INTEGER))、 SUM(CONVERT(B16、INTEGER)) を選択:FK1 = 53 AND FK2 = 3 */ /* scanCount:50001 */ WHERE(FK1 = 53) AND(FK2 = 3) /* 合計:55199 MASTER.IDX_COMP読み取り:481(0%) MASTER.MASTER_DATAリード:54718(99%) */ (1 Datensatz、27368 ms) – Peter

答えて

2

プロファイラの出力によれば、主な問題(93%)はディスクからの読み取りです。

@prof_start; 
SELECT ... FROM master WHERE fk1=53 AND fk2=3; 
@prof_stop; 

となった:私は、H2コンソールでこれを実行しました

Profiler: top 3 stack trace(s) of 48039 ms [build-158]: 
4084/4376 (93%): 
at java.io.RandomAccessFile.readBytes(Native Method) 
at java.io.RandomAccessFile.read(RandomAccessFile.java:338) 
at java.io.RandomAccessFile.readFully(RandomAccessFile.java:397) 
at org.h2.store.FileStore.readFully(FileStore.java:285) 
at org.h2.store.PageStore.readPage(PageStore.java:1253) 
at org.h2.store.PageStore.getPage(PageStore.java:707) 
at org.h2.index.PageDataIndex.getPage(PageDataIndex.java:225) 
at org.h2.index.PageDataNode.getRowWithKey(PageDataNode.java:269) 
at org.h2.index.PageDataNode.getRowWithKey(PageDataNode.java:270) 

EXPLAIN ANALYZE SELECTによると、それはディスクから55'000以上のページを読んでいる(2キロバイトに各ページを110 MB)このクエリのために。このようなクエリで他のデータベースがどのように動作するかはわかりません。しかし、可能であれば、より少ないデータを読み込むようにクエリを変更する必要があると思います。

+1

テストケースでは、シャットダウンのデフラグが遅いのはなぜですか?なぜ私はサーバーを再起動した後、遅いステートメントが速いですか? – Peter

1

h2が、それはすでに完了データ型の変換を持つ一時テーブル/ビューを持つことは可能ですか?主なテーブルからその更新自体を(時折夜間に)実行することが可能な場合は、すでに完了している変換に多くの処理能力があります。

これが実現できない場合は、「b」列ごとに1つずつ、b#= 1を引くだけで複数のサブ選択を行うことができます。SUMの代わりにCOUNTを実行します。よく例えば:

SELECT (count1+count2) AS Count, 
(SELECT COUNT(*) FROM master WHERE fk1=53 AND fk2=3 AND b1=1) AS count1 
(SELECT COUNT(*) FROM master WHERE fk1=53 AND fk2=3 AND b2=1) AS count2 

私はその正確な構文は、あなたのプログラムで動作するかどうかわからないんだけど、うまくいけば、一般的なSQLのアイデアとして、それは正しい軌道に乗ってあなたを取得します。

+0

私はあなたの最初のsu私のテストケースではbooleanをtinyintに置き換えてggestionを実行します。 select文は、SELECT count(*)、SUM(b1)... SUM(b16) のようになります。 – Peter

+0

さらに、fk1 = 93、fk2 = 3、b2 = 1の場合、SELECT COUNT(*)からマスターまでの時間は15秒です。より大きい(tinyint> boolean)データベースは応答時間が悪くなります。 – Peter

+0

これは、50k行の合計でゴソゴトしています(上記のコメントが正しく理解されていれば、サブクエリあたり50kか合計行は50kですか?)。あなたが3列のインデックス*を持っているという事実はそれに貢献するかもしれません。 3つすべてを1つのインデックスとして索引付けする理由は何ですか?あなたの最も面倒なクエリにfk3が存在しないように思えるので、なぜインデックスを作成するのが難しいのでしょうか。 – roberttdev

関連する問題