web-dev-qa-db-fra.com

HDF5 - simultanéité, compression et performances d'E / S

J'ai les questions suivantes sur les performances HDF5 et la concurrence:

  1. HDF5 prend-il en charge l'accès en écriture simultané?
  2. En dehors des considérations de concurrence, comment sont les performances HDF5 en termes de performances d'E/S (ne taux de compression affecte les performances)?
  3. Puisque j'utilise HDF5 avec Python, comment ses performances se comparent-elles à Sqlite?

Les références:

63

Mis à jour pour utiliser pandas 0.13.1

1) Non. http://pandas.pydata.org/pandas-docs/dev/io.html#notes-caveats . Il existe différentes façons de faire , par exemple Demandez à vos différents threads/processus d'écrire les résultats du calcul, puis de combiner un seul processus.

2) En fonction du type de données que vous stockez, de la façon dont vous le faites et de la façon dont vous souhaitez les récupérer, le HDF5 peut offrir de bien meilleures performances. Le stockage dans un HDFStore sous la forme d'un tableau unique, les données flottantes, compressées (en d'autres termes, ne les stockent pas dans un format permettant l'interrogation), seront stockées/lues incroyablement rapidement. Même le stockage au format tableau (qui ralentit les performances d'écriture), offrira de très bonnes performances d'écriture. Vous pouvez regarder ceci pour quelques comparaisons détaillées (c'est ce que HDFStore utilise sous le capot). http://www.pytables.org/ , voici une belle photo: 

(et depuis PyTables 2.3, les requêtes sont maintenant indexées), donc la performance est en fait BEAUCOUP mieux que cela. Donc, pour répondre à votre question, si vous voulez tout type de performance, HDF5 est le chemin à parcourir.

L'écriture:

In [14]: %timeit test_sql_write(df)
1 loops, best of 3: 6.24 s per loop

In [15]: %timeit test_hdf_fixed_write(df)
1 loops, best of 3: 237 ms per loop

In [16]: %timeit test_hdf_table_write(df)
1 loops, best of 3: 901 ms per loop

In [17]: %timeit test_csv_write(df)
1 loops, best of 3: 3.44 s per loop

En train de lire

In [18]: %timeit test_sql_read()
1 loops, best of 3: 766 ms per loop

In [19]: %timeit test_hdf_fixed_read()
10 loops, best of 3: 19.1 ms per loop

In [20]: %timeit test_hdf_table_read()
10 loops, best of 3: 39 ms per loop

In [22]: %timeit test_csv_read()
1 loops, best of 3: 620 ms per loop

Et voici le code

import sqlite3
import os
from pandas.io import sql

In [3]: df = DataFrame(randn(1000000,2),columns=list('AB'))
<class 'pandas.core.frame.DataFrame'>
Int64Index: 1000000 entries, 0 to 999999
Data columns (total 2 columns):
A    1000000  non-null values
B    1000000  non-null values
dtypes: float64(2)

def test_sql_write(df):
    if os.path.exists('test.sql'):
        os.remove('test.sql')
    sql_db = sqlite3.connect('test.sql')
    sql.write_frame(df, name='test_table', con=sql_db)
    sql_db.close()

def test_sql_read():
    sql_db = sqlite3.connect('test.sql')
    sql.read_frame("select * from test_table", sql_db)
    sql_db.close()

def test_hdf_fixed_write(df):
    df.to_hdf('test_fixed.hdf','test',mode='w')

def test_csv_read():
    pd.read_csv('test.csv',index_col=0)

def test_csv_write(df):
    df.to_csv('test.csv',mode='w')    

def test_hdf_fixed_read():
    pd.read_hdf('test_fixed.hdf','test')

def test_hdf_table_write(df):
    df.to_hdf('test_table.hdf','test',format='table',mode='w')

def test_hdf_table_read():
    pd.read_hdf('test_table.hdf','test')

Bien sûr, YMMV.

76
Jeff

Regardez pytables, ils ont peut-être déjà fait beaucoup de travail pour vous.

Cela dit, je ne sais pas exactement comment comparer le hdf et le sqlite. hdf est un format de fichier de données hiérarchique à usage général + bibliothèques et sqlite est une base de données relationnelle.

hdf prend en charge les E/S parallèles au niveau c, mais je ne sais pas dans quelle mesure h5py encapsule ou s'il jouera Nice avec NFS.

Si vous voulez vraiment une base de données relationnelle hautement concurrente, pourquoi ne pas simplement utiliser un vrai serveur SQL?

2
tacaswell