我正在进行大规模的风力模拟,以便在城市上产生每小时的风力模式。结果是二维轮廓的时间序列。目前,我将结果存储在具有以下结构的SQLite3
数据库表中
Table: CFD
id, timestamp, velocity, cell_id
1 , 2010-01-01 08:00:00, 3.345, 1
2 , 2010-01-01 08:00:00, 2.355, 2
3 , 2010-01-01 08:00:00, 2.111, 3
4 , 2010-01-01 08:00:00, 6.432, 4
.., ..................., ....., .
1000 , 2010-01-01 09:00:00, 3.345, 1
1001 , 2010-01-01 10:00:00, 2.355, 2
1002 , 2010-01-01 11:00:00, 2.111, 3
1003 , 2010-01-01 12:00:00, 6.432, 4
.., ..................., ....., .
实际创建声明:
CREATE TABLE cfd(id INTEGER PRIMARY KEY, time DATETIME, u, cell_id integer)
CREATE INDEX idx_cell_id_cfd on cfd(cell_id)
CREATE INDEX idx_time_cfd on cfd(time)
(这些表中有三个,每个表用于不同的结果变量)
其中cell_id
是对域中代表城市中某个位置的单元格的引用。请参阅此图片,了解特定时间步长的效果。
典型的查询在时间维度上执行某种聚合,并在cell_id
上执行分组。例如,如果我想知道特定时间间隔内每个小区的平均局部风速,我会执行
select sum(time in ('2010-01-01 08:00:00','2010-01-01 13:00:00','2010-01-01 14:00:00', ...................., ,'2010-12-30 18:00:00','2010-12-30 19:00:00','2010-12-30 20:00:00','2010-12-30 21:00:00') and u > 5.0) from cfd group by cell_id
时间戳的数量可以在100到8,000之间变化。
这适用于小型数据库,但对于大型数据库来说速度要慢得多。例如,我的最后一个数据库是60GB,3个表,每个表有222,000,000行。
有更好的方法来存储数据吗?例如:
我已采用此question中的所有建议来最大限度地提高效果。
答案 0 :(得分:1)
此特定查询很难优化,因为必须在所有表行上计算sum()
。最好使用WHERE:
SELECT count(*)
FORM cfd
WHERE time IN (...)
AND u > 5
GROUP BY cell_id;
如果可能,请使用更简单的表达式来过滤时间,例如time BETWEEN a AND b
。
使用covering index可能是值得的,或者在这种情况下,当所有查询按时间过滤时,clustered index(没有其他索引):
CREATE TABLE cfd (
cell_id INTEGER,
time DATETIME,
u,
PRIMARY KEY (cell_id, time)
) WITHOUT ROWID;