H2优化select语句/关闭碎片整理

时间:2011-08-02 12:24:20

标签: select h2 defragmentation

测试用例:

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是持久缓存吗?

基础设施:WebBrowser< - > H2控制台服务器< - > H2 DB:h2 1.3.158

2 个答案:

答案 0 :(得分:2)

根据分析器输出,主要问题(93%)是从磁盘读取。我在H2控制台中运行了这个:

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

得到了:

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 KB; 110 MB)。我不确定其他数据库如何执行此类查询。但我想如果可能的话,应该更改查询,以便读取更少的数据。

答案 1 :(得分:1)

是否可以拥有已完成数据类型转换的临时表/视图?如果有可能偶尔从主表中进行更新(一晚一次左右),那么你已经有很多处理能力进入已完成的转换。

如果这不可行,你可能想要做多个子选择,每个“b”列一个,你只拉动b#= 1.然后做一个COUNT而不是SUM,这应该更快。例如:

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想法,它可以让您走上正确的轨道。

相关问题