Mongodb 存储、写入和读取大型气象数据集的更好方法

Mongodb 存储、写入和读取大型气象数据集的更好方法,mongodb,hdf5,netcdf,bigdata,Mongodb,Hdf5,Netcdf,Bigdata,我正在寻找一个更好的存储,写入和读取气象数据(约30GB的原始文本格式) 目前我正在使用NetCDF文件格式来存储天气记录。在这个NetCDF文件中,我有3个维度:时间,气候变量,位置。但是维度顺序是我的任务的关键约束(见下文) 第一项任务是每天更新约3000个气象站的天气记录。维度顺序(时间、变量、名称)提供了最佳的写入性能,因为新数据将添加到NetCDF文件的末尾 第二项任务是读取所有每日天气记录,以便站点进行分析。维度顺序(名称、变量、时间)提供了最佳的读取性能,因为一个站点的所有记录都存

我正在寻找一个更好的存储,写入和读取气象数据(约30GB的原始文本格式)

目前我正在使用NetCDF文件格式来存储天气记录。在这个NetCDF文件中,我有3个维度:
时间
气候变量
位置
。但是维度顺序是我的任务的关键约束(见下文)

第一项任务是每天更新约3000个气象站的天气记录。维度顺序
(时间、变量、名称)
提供了最佳的写入性能,因为新数据将添加到NetCDF文件的末尾

第二项任务是读取所有每日天气记录,以便站点进行分析。维度顺序
(名称、变量、时间)
提供了最佳的读取性能,因为一个站点的所有记录都存储在一起

这两个任务具有NetCDF文件的冲突设计(在一个任务中性能最好,但在另一个任务中性能最差)

我的问题是,是否有其他方法/软件/数据格式来存储、写入和读取我的数据集,以提供两项任务的最佳性能?由于我每天都要重复这两个步骤,而且数据分析非常耗时,因此我需要找到一种将I/O最小化的最佳方法


谢谢你的建议。如果我的问题不清楚,请告诉我。

好的,你需要的是分块。我创建了一个小的python脚本进行测试,没有对其进行分块,它基本上证实了您的观察,即在一维中访问速度很慢。我测试了3000个站点,每个站点10个变量和10000个时间步。我确实把站和变量放在同一个维度进行测试,但是如果你真的需要的话,它应该在3D的情况下给出类似的结果。 不分块的测试输出:

文件分块类型:无
可变形状:(30000,10000)
创建文件的总时间:13.665503025054932
添加一次测量时间的平均时间:0.00136328568459 0.00148195505142 0.0018851685524
在打开单个文件的情况下逐个读取所有时间序列
每个站点/变量的平均读取时间:0.524109539986

对于分块:

文件分块类型:[100100]
可变形状:(30000,10000)
创建文件的总时间:18.610711812973022
添加一个测量时间的平均时间:0.00185681316853 0.00168470859528 0.00213300466537
在打开单个文件的情况下逐个读取所有时间序列
每个站点/变量的平均读取时间:0.000948731899261

您可以看到,分块将写入时间增加了约50%,但显著地提高了读取时间。我没有尝试优化块大小,只是测试了它是否朝着正确的方向工作。 如果代码不清楚或者您不熟悉python,请随时询问

# -*- coding: utf-8 -*-
from time import time
import numpy as np
from netCDF4 import Dataset

test_dataset_name='test_dataset.nc4'
num_stations=3000 
num_vars=10 
chunks=None
#chunks=[100,100]

def create_dataset():
    ff=Dataset(test_dataset_name,'w')
    ff.createDimension('Time',None)
    ff.createDimension('Station_variable',num_stations*num_vars)
    if chunks:
        var1=ff.createVariable('TimeSeries','f8',   ('Station_variable','Time'),chunksizes=chunks)
    else:
        var1=ff.createVariable('TimeSeries','f8',('Station_variable','Time'))
    return ff

def add_data(ff,timedim):
    var1=ff.variables['TimeSeries']
    var1[0:1000,timedim]=timedim*np.ones((1000),'f8')

def dataset_close(inds):
    inds.close()

## CREATE DATA FILE    
time_start=time()
time1=[]
time2=[]
time3=[]
time4=[]
testds=create_dataset()
dataset_close(testds)
for i in range(10000):
    time1.append(time())
    ff=Dataset(test_dataset_name,'a')
    time2.append(time())
    add_data(ff,i)
    time3.append(time())
    ff.sync()
    ff.close()
    time4.append(time())
time_end=time()

time1=np.array(time1)
time2=np.array(time2)
time3=np.array(time3)
time4=np.array(time4)

## READ ALL STAION-VARIABLE COMBINATIONS AS ONE TIMESERIES
ff=Dataset(test_dataset_name,'r')
## PRINT DATA FILE CREATION SUMMARY
print("File chunking type:",chunks)
print("Variable shape:",ff.variables['TimeSeries'][:].shape)
print("Total time, file creation:", time_end-time_start)
print("Average time for adding one measurement time: ",np.mean(time4-    time1), np.mean(time4[:100]-time1[:100]),np.mean(time4[-100:]- time1[-100:]))
print("Read all timeseries one by one with single file open")
time_rstart=[]
time_rend=[]
for i in range(0,ff.variables['TimeSeries'][:].shape[0],int(ff.variables['TimeSeries'][:].shape[0]/100)):
    time_rstart.append(time())
    dataline=ff.variables['TimeSeries'][i,:]
    time_rend.append(time())
time_rstart=np.array(time_rstart)
time_rend=np.array(time_rend)
print("Average read time per station/variable: ",np.mean(time_rend-  time_rstart))

首先想到的是:你在使用压缩吗?这将大大减少I/O。如果您正确订购数据,3000个站点听起来不会太多。您如何定义您的数据,将所有气象变量定义为单独的NetCDF变量,或将所有数据定义为一个变量?我会尝试后一个版本,这样每次添加新数据都可以通过添加一个数组来完成。还要检查您是否拥有最新的netcdf+hdf库。我个人认为压缩对您的案例没有多大好处,因为在添加数据时,您应该先解压缩现有数据,然后添加数据并进行压缩again@kakk11. 我同意你的看法。我的数据集不是很大,压缩会降低性能。我的困难在于,读写需要两种相反的数据结构才能获得更好的性能,就像我在问题中所问的那样。具有最佳写入性能的数据结构具有最差的读取性能,反之亦然。我还尝试将单个电台的记录存储到单个文件中,这样可以平衡读写性能。但是,
open
和netcdf文件的操作非常耗时(例如,一个文件需要0.5秒,3100个文件需要26分钟)。@AF7正如kakk11所建议的那样,在我的情况下,压缩没有帮助,因为所有数据都必须先解压缩,然后再重新压缩,以供参考。你能为我工作吗。我不认为我完全理解分块是如何在nc格式下工作的。你能给我解释一下吗?很高兴我能帮上忙。分块实际上不是NetCDF4的功能,而是HDF5的功能,HDF5提供了参考底图工具。简单地说,分块是数据在磁盘上切片的方式:一个分块是连续的数据数组,可以快速访问。所以,不用从磁盘上逐个读取数字,而是可以逐块读取。我不是一个很好的专家,无法解释它是如何在多维无限数组上工作的,以及为什么它不会显著影响编写性能。更多信息