设置不可能更简单:
select count(*) from requestrepository where request_type = 'ADD'
我做什么:(0)运行analyze
,(1)通过键字段删除一行,(2)为刚刚删除的键插入一行,(3)运行上面引用的查询,计数到10并重复。
我看到的内容:上面提到的查询每次需要3到5秒,explain analyze
说:
SELECT
COUNT(*)
FROM PUBLIC.REQUESTREPOSITORY
/* PUBLIC.IX_REQUESTS: REQUEST_TYPE = 'ADD' */
/* scanCount: 12098748 */
WHERE REQUEST_TYPE = 'ADD'
/*
REQUESTREPOSITORY.IX_REQUESTS read: 126700
*/
我在不同的机器上尝试了相同的数据库,硬件/ linux / ssd,VM / Windows / netapp,但趋势总是一样:count(*)
也需要(?)长。
这是我不确定的。可以预料这需要很长时间吗?我原以为至少在第二轮中,缓存已经填满了,而且速度要快得多,但explain analyze
总是列出126700个读取。
有关H2参数或设置如何改进的任何提示均值得赞赏。
编辑(不确定这是否应该作为答案)
与此同时,我们尝试了很多东西,包括mvstore,1.4.x,并行线程,具有不同磁盘的计算机,Linux,Windows。情况总是一样的。占用10或1200万行,一个varchar列,其中包含三个状态值,例如PROCESSING,ADD,DELETE,列上的索引和一个严重过多的状态:然后count(*) where colname='ADD'
之类的内容需要1到几秒之后每次更新表格。
为了防止这种情况造成问题,我们最终修复了我们自己的代码,该代码执行了三个count(*)
,每个状态一个,而不是一个group by
,并且每5秒运行一次而不是随需应变。当然不是我们最好的设计。
我唯一的理由是,我仍然感到惊讶的是count(*)
在这样的设置中需要很长时间。我的预感是必须通过在更新后真正计数来计算索引的计数,而我预计计数可以在某处读取数据结构。 (没有批评,我自己肯定无法实现数据库。)
答案 0 :(得分:0)
不确定H2,但您是否尝试过COUNT(request_type)
而不是COUNT(*)
?
SQL标准的COUNT(*)
往往需要很长时间才能进行计算,因为它需要全表扫描来过滤掉仅包含NULL
值的行。
在单个索引列上使用COUNT()
可以加快速度。这样就不需要读取表行了,因为索引足以决定列的值是否为NULL。