【问题标题】:A better approach to store, write, and read a big dataset of meteorological data存储、写入和读取大型气象数据数据集的更好方法
【发布时间】:2016-01-22 12:09:12
【问题描述】:

我希望更好地存储、写入和读取气象数据(原始文本格式大约 30 GB)。

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

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

第二个任务是读取一个站点的所有每日天气记录以进行分析。维度顺序(name, var, time) 提供了最佳的读取性能,因为一个站点的所有记录都存储在一起。

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

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

感谢您的任何建议。如果我的问题不清楚,请告诉我。

【问题讨论】:

  • 首先想到的是:你在使用压缩吗?这将大大减少 I/O。
  • 3000 个电台听起来不会太多,如果您正确订购数据的话。您如何将您的数据、所有气象变量定义为单独的 NetCDF 变量或一个变量中的所有内容?我会尝试后一个版本,这样每次添加新数据都可以通过添加一个数组来完成。还要检查您是否拥有最新的 netcdf+hdf 库。我个人认为压缩对您的情况没有太大好处,因为添加数据时您应该先解压缩现有数据,添加数据并再次压缩
  • @kakk11。我同意你的看法。我的数据集不是很大,压缩会降低性能。我的困难是阅读和写作需要两个相反的数据结构以获得更好的性能,就像我在我的问题中所问的那样。具有最佳写入性能的数据结构具有最差的读取性能,反之亦然。我也尝试将单个站点的记录存储到一个单独的文件中,这样可以平衡读写的性能。但是,open 和 netcdf 文件的操作是耗时的(例如一个文件 0.5 秒,3100 个文件 26 分钟)。
  • @AF7 正如 kakk11 所建议的那样,压缩对我的情况没有帮助,因为所有数据都必须先解压缩,然后再压缩

标签: mongodb hdf5 netcdf bigdata


【解决方案1】:

好的,你需要的是分块。我创建了一个小的 python 脚本来测试,没有分块它基本上证实了您观察到访问在一个维度上很慢。我使用站号 3000、每个站的变量 10 和时间步长 10000 进行了测试。我确实将站和变量放入相同的维度进行测试,但如果你真的需要它,它应该在 3D 案例中给出类似的结果。 我的测试输出没有分块:

File chunking type: None Variable shape: (30000, 10000) Total time, file creation: 13.665503025054932 Average time for adding one measurement time: 0.00136328568459 0.00148195505142 0.0018851685524 Read all timeseries one by one with single file open Average read time per station/variable: 0.524109539986

还有分块:

File chunking type: [100, 100] Variable shape: (30000, 10000) Total time, file creation: 18.610711812973022 Average time for adding one measurement time: 0.00185681316853 0.00168470859528 0.00213300466537 Read all timeseries one by one with single file open Average read time per station/variable: 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))

【讨论】:

  • 感谢您的建议。分块为我工作。我不认为我完全理解分块是如何以 nc 格式工作的。你愿意给我更多的解释吗?
  • 很高兴我能帮上忙。分块实际上不是 NetCDF4 的功能,而是 HDF5 的功能,它提供了底层工具。简单地说,分块是数据在磁盘上的切片方式:一个块是连续的数据数组,可以快速访问。因此,不是从磁盘中逐个读取数字,而是可以逐块读取它们。我没有足够的专家来解释它实际上是如何在多维无限数组上工作的,以及为什么它不会显着损害写作性能。更多信息hdfgroup.org/HDF5/doc/Advanced/Chunking
猜你喜欢
  • 2013-05-30
  • 1970-01-01
  • 2011-11-05
  • 2011-04-04
  • 2021-09-20
  • 2018-08-04
  • 2021-02-10
  • 2016-11-24
  • 1970-01-01
相关资源
最近更新 更多