Лучший подход к хранению, записи и чтению большого набора метеорологических данных.

Я ищу лучшее для хранения, записи и чтения метеорологических данных (около 30 ГБ в формате необработанного текста).

В настоящее время я использую формат файла NetCDF для хранения записей о погоде. В этом файле NetCDF у меня есть 3 измерения: time, climate variables, locations. Но порядок измерений является ключевым ограничением для моих задач (см. ниже).

Первая задача — ежедневно обновлять записи о погоде примерно для 3000 метеостанций. Порядок измерения (time, var, name) обеспечивает наилучшую производительность для записи, так как новые данные будут добавляться в конец файла NetCDF.

Вторая задача - прочитать все ежедневные записи погоды для станции, чтобы выполнить анализ. Порядок измерения (name, var, time) обеспечивает наилучшую производительность для чтения, так как все записи одного сайта хранятся вместе.

Две задачи имеют конфликтную структуру файла NetCDF (наилучшая производительность в одной задаче, но наихудшая производительность в другой задаче).

Мои вопросы заключаются в том, существуют ли альтернативные методы/программное обеспечение/формат данных для хранения, записи и чтения моих наборов данных, чтобы обеспечить наилучшую производительность моих двух задач? Поскольку мне приходится повторять эти два шага каждый день, а анализ данных занимает много времени, мне нужно найти лучший способ минимизировать ввод-вывод.

Спасибо за любые предложения. Пожалуйста, дайте мне знать, если мой вопрос не ясен.


person Bangyou    schedule 23.10.2015    source источник
comment
Первое, что приходит на ум: вы используете сжатие? Это значительно уменьшит ввод-вывод.   -  person AF7    schedule 23.10.2015
comment
3000 станций не кажутся слишком большими, если правильно упорядочить данные. Как вы определяете свои данные, все метеорологические переменные как отдельные переменные NetCDF или все в одной переменной? Я бы попробовал последний вариант, чтобы каждый раз добавлять новые данные можно было путем добавления одного единственного массива. Также проверьте наличие новейших библиотек netcdf+hdf. Я лично не думаю, что сжатие имеет большую пользу для вашего случая, потому что при добавлении данных вы должны сначала распаковать существующие данные, добавить данные и снова сжать   -  person kakk11    schedule 24.10.2015
comment
@какк11. Я с тобой согласен. Мой набор данных не очень большой, и сжатие снизит производительность. Моя трудность заключается в том, что для чтения и записи требуются две противоположные структуры данных для повышения производительности, как я задал в своем вопросе. Структура данных для лучшей производительности записи имеет худшую производительность чтения, и наоборот. Я также попытался сохранить записи отдельных станций в отдельный файл, что позволит сбалансировать производительность чтения и записи. Однако операция open и файла netcdf занимает много времени (например, 0,5 с для файла, 26 мин для 3100 файлов).   -  person Bangyou    schedule 25.10.2015
comment
@ AF7 Как предложил kakk11, сжатие в моей ситуации не помогает, так как все данные нужно сначала распаковать, а затем снова сжать.   -  person Bangyou    schedule 25.10.2015


Ответы (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))
person kakk11    schedule 25.10.2015
comment
Спасибо за ваше предложение. Чанкинг работает на меня. Я не думаю, что полностью понимаю, как фрагментация работает в формате nc. Хотите дать мне больше объяснений по этому поводу? - person Bangyou; 26.10.2015
comment
Рад, что смог помочь. Фрагментирование на самом деле является функцией не NetCDF4, а HDF5, который предоставляет базовые инструменты. Проще говоря, фрагментация — это способ разделения данных на диске: один фрагмент представляет собой непрерывный массив данных, к которому можно быстро получить доступ. Таким образом, вместо того, чтобы читать числа по одному с диска, их можно читать по частям. Я недостаточно хороший эксперт, чтобы объяснить, как это на самом деле работает с многомерными неограниченными массивами и почему это не сильно влияет на производительность записи. Подробнее hdfgroup.org/HDF5/doc/Advanced/Chunking - person kakk11; 26.10.2015