HDF5

HDF5 插件可将 HDF5 文件导入 DolphinDB,并支持进行数据类型转换。

在插件市场安装插件

版本要求

  • DolphinDB Server: 2.00.10及更高版本

安装步骤

  1. 在DolphinDB 客户端中使用 listRemotePlugins 命令查看插件仓库中的插件信息。

    login("admin", "123456")
    listRemotePlugins()
  2. 使用 installPlugin 命令完成插件安装。

    installPlugin("hdf5")
  3. 使用 loadPlugin 命令加载插件。

    loadPlugin("hdf5")

用户接口

hdf5::ls

语法

hdf5::ls(fileName)

参数

  • fileName:HDF5文件名,类型为string。

详情

列出一个HDF5文件中的所有对象(数据集(dataset)和组(group))以及对象类型(objType)。在对象类型中,数据集会包括其列数及行数。例如DataSet{(7,3)}代表7列3行。

例子

hdf5::ls("/smpl_numeric.h5")

output:
        objName	     objType
        --------------------
        /            Group
        /double	     DataSet{(7,3)}
        /float	     DataSet{(7,3)}
        /schar	     DataSet{(7,3)}
        /sint	     DataSet{(7,3)}
        /slong	     DataSet{(7,3)}
        /sshort	     DataSet{(7,3)}
        /uchar	     DataSet{(7,3)}
        /uint	     DataSet{(7,3)}
        /ulong	     DataSet{(1,1)}
        /ushort	     DataSet{(7,3)}

hdf5::ls("/named_type.h5")

output:
        objName      objType
        ----------------------
        /            Group      
        /type_name   NamedDataType

hdf5::lsTable

语法

hdf5::lsTable(fileName)

参数

  • fileName:HDF5文件名,类型为string。

详情

列出一个HDF5文件中的所有table信息,即HDF5数据集(dataset)对象信息,包括表名、列数及行数、表的类型。

例子

hdf5::lsTable("/smpl_numeric.h5")

output:
       tableName    tableDims	 tableType
       /double        7,3       H5T_NATIVE_DOUBLE
       /float	      7,3       H5T_NATIVE_FLOAT
       /schar	      7,3       H5T_NATIVE_SCHAR
       /sint	      7,3       H5T_NATIVE_INT
       /slong	      7,3       H5T_NATIVE_LLONG
       /sshort	      7,3       H5T_NATIVE_SHORT
       /uchar	      7,3       H5T_NATIVE_UCHAR
       /uint	      7,3       H5T_NATIVE_UINT
       /ulong	      1,1       H5T_NATIVE_ULLONG
       /ushort	      7,3       H5T_NATIVE_USHORT

hdf5::extractHDF5Schema

语法

hdf5::extractHDF5Schema(fileName, datasetName)

参数

  • fileName:HDF5文件名,类型为字符串标量。
  • datasetName:dataset名称,即表名。可通过ls或lsTable获得,类型为字符串标量。

详情

生成HDF5文件中指定数据集的结构,包括两列:列名和数据类型。

例子

hdf5::extractHDF5Schema("/smpl_numeric.h5","sint")

output:
        name	type
        col_0	INT
        col_1	INT
        col_2	INT
        col_3	INT
        col_4	INT
        col_5	INT
        col_6	INT


hdf5::extractHDF5Schema("/compound.h5","com")

output:
        name	type
        fs	STRING
        vs	STRING
        d	DOUBLE
        t	TIMESTAMP
        l	LONG
        f	FLOAT
        i	INT
        s	SHORT
        c	CHAR

hdf5::loadHDF5

语法

hdf5::loadHDF5(fileName,datasetName,[schema],[startRow],[rowNum])

参数

  • fileName:HDF5文件名,类型为字符串标量。
  • datasetName:dataset名称,即表名。可通过ls或lsTable获得,类型为字符串标量。
  • schema:包含列名和列的数据类型的表。若要改变由系统自动决定的列的数据类型,需要在schema表中修改数据类型,并且把它作为loadHDF5函数的一个参数。
  • startRow:从哪一行开始读取HDF5数据集。若不指定,默认从数据集起始位置读取。
  • rowNum:读取HDF5数据集的行数。若不指定,默认读到数据集的结尾。

详情

将HDF5文件中的指定数据集加载为DolphinDB数据库的内存表。读取的行数为HDF5文件中定义的行数,而不是读取结果中的DolphinDB表的行数。支持的数据类型,以及数据转化规则可见支持的数据类型章节。

例子

hdf5::loadHDF5("/smpl_numeric.h5","sint")

output:
        col_0	col_1	col_2	col_3	col_4	col_5	col_6
        (758)	8	(325,847)	87	687	45	90
        61	0	28	77	546	789	45
        799	5,444	325,847	678	90	54	0


scm = table(`a`b`c`d`e`f`g as name, `CHAR`BOOL`SHORT`INT`LONG`DOUBLE`FLOAT as type)
hdf5::loadHDF5("../hdf5/h5file/smpl_numeric.h5","sint",scm,1,1)

output:
        a	b	c	d	e	f	g
        '='	false	28	77	546	789	45

注意 :数据集的dataspace维度必须小于等于2。只有一维或二维表可以被解析。

hdf5::loadPandasHDF5

语法

hdf5::loadPandasHDF5(fileName,groupName,[schema],[startRow],[rowNum])

参数

  • fileName:由Pandas保存的HDF5文件名,类型为字符串标量。
  • groupName:group的标识符,即key名。
  • schema:包含列名和列的数据类型的表。若要改变由系统自动决定的列的数据类型,需要在schema表中修改数据类型,并且把它作为loadPandasHDF5函数的一个参数。
  • startRow:从哪一行开始读取HDF5数据集。若不指定,默认从数据集起始位置读取。
  • rowNum:读取HDF5数据集的行数。若不指定,默认读到数据集的结尾。

详情

将由Pandas保存的HDF5文件中的指定数据表加载为DolphinDB数据库的内存表。读取的行数为HDF5文件中定义的行数,而不是读取结果中的DolphinDB表的行数。支持的数据类型,以及数据转化规则可见支持的数据类型章节。

例子

hdf5::loadPandasHDF5("../hdf5/h5file/data.h5","/s",,1,1)

output:
        A	 B	C  D  E
        28 77	54 78 9

hdf5::loadHDF5Ex

语法

hdf5::loadHDF5Ex(dbHandle,tableName,[partitionColumns],fileName,datasetName,[schema],[startRow],[rowNum],[tranform])

参数

  • dbHandle与tableName:若要将输入数据文件保存在分布式数据库中,需要指定数据库句柄和表名。
  • partitionColumns:字符串标量或向量,表示分区列。当分区数据库不是SEQ分区时,我们需要指定分区列。在组合分区中,partitionColumns是字符串向量。
  • fileName:HDF5文件名,类型为字符串标量。
  • datasetName:dataset名称,即表名,可通过ls或lsTable获得,类型为字符串标量。
  • schema:包含列名和列的数据类型的表。如果我们想要改变由系统自动决定的列的数据类型,需要在schema表中修改数据类型,并且把它作为loadHDF5Ex函数的一个参数。
  • startRow:读取HDF5数据集的起始行位置。若不指定,默认从数据集起始位置读取。
  • rowNum:读取HDF5数据集的行数。若不指定,默认读到数据集的结尾。
  • tranform:一元函数,并且该函数接受的参数必须是一个表。如果指定了transform参数,需要先创建分区表,再加载数据,程序会对数据文件中的数据执行transform参数指定的函数,再将得到的结果保存到数据库中。

详情

将HDF5文件中的数据集转换为DolphinDB数据库的分布式表,然后将表的元数据加载到内存中。读取的行数为HDF5文件中定义的行数,而不是读取结果中的DolphinDB表的行数。支持的数据类型,以及数据转化规则可见支持的数据类型章节。

例子

  • 磁盘上的SEQ分区表
db = database("seq_on_disk", SEQ, 16)
hdf5::loadHDF5Ex(db,`tb,,"/large_file.h5", "large_table")
  • 内存中的SEQ分区表
db = database("", SEQ, 16)
hdf5::loadHDF5Ex(db,`tb,,"/large_file.h5", "large_table")
  • 磁盘上的非SEQ分区表
db = database("non_seq_on_disk", RANGE, 0 500 1000)
hdf5::loadHDF5Ex(db,`tb,`col_4,"/smpl_numeric.h5","sint")
  • 内存中的非SEQ分区表
db = database("", RANGE, 0 500 1000)
t0 = hdf5::loadHDF5Ex(db,`tb,`col_4,"/smpl_numeric.h5","sint")
  • 内存中的非SEQ分区表
db = database("", RANGE, 0 500 1000)
t0 = hdf5::loadHDF5Ex(db,`tb,`col_4,"/smpl_numeric.h5","sint")
  • 指定transform 将数值类型表示的日期和时间(比如:20200101)转化为指定类型(比如:日期类型)
dbPath="dfs://DolphinDBdatabase"
db=database(dbPath,VALUE,2020.01.01..2020.01.30)
dataFilePath="/transform.h5"
datasetName="/SZ000001/data"
schemaTB=hdf5::extractHDF5Schema(dataFilePath,datasetName)
update schemaTB set type="DATE" where name="trans_time"
tb=table(1:0,schemaTB.name,schemaTB.type)
tb1=db.createPartitionedTable(tb,`tb1,`trans_time);
def i2d(mutable t){
    return t.replaceColumn!(`trans_time,datetimeParse(string(t.trans_time),"yyyyMMdd"))
}
t = hdf5::loadHDF5Ex(db,`tb1,`trans_time,dataFilePath,datasetName,,,,i2d)

hdf5::HDF5DS

语法

hdf5::HDF5DS(fileName,datasetName,[schema],[dsNum])

参数

  • fileName:HDF5文件名,类型为字符串标量。
  • datasetName:数据集名,即表名。可通过lslsTable获得,类型为字符串标量。
  • schema:包含列名和列的数据类型的表。若要改变由系统自动决定的列的数据类型,需要在schema表中修改数据类型,并且把它作为HDF5DS函数的一个参数。
  • dsNum:需要生成的数据源数量。整个表会被均分为dsNum份。如果不指定,默认生成1个数据源。

详情

根据输入的文件名和数据集名创建数据源列表。

例子

>ds = hdf5::HDF5DS(smpl_numeric.h5","sint")
>size ds;
1
>ds[0];
DataSource< loadHDF5("/smpl_numeric.h5", "sint", , 0, 3) >

>ds = hdf5::HDF5DS(smpl_numeric.h5","sint",,3)
>size ds;
3
>ds[0];
DataSource< loadHDF5("/smpl_numeric.h5", "sint", , 0, 1) >
>ds[1];
DataSource< loadHDF5("/smpl_numeric.h5", "sint", , 1, 1) >
>ds[2];
DataSource< loadHDF5("/smpl_numeric.h5", "sint", , 2, 1) >

注意 :HDF5不支持并行读入。以下例子是错误示范和正确示范。

错误示范

ds = hdf5::HDF5DS("/smpl_numeric.h5", "sint", ,3)
res = mr(ds, def(x) : x)

正确示范,将mr parallel参数设为false

ds = hdf5::HDF5DS("/smpl_numeric.h5", "sint", ,3)
res = mr(ds, def(x) : x,,,false)

hdf5::saveHDF5

语法

hdf5::saveHDF5(table, fileName, datasetName, [append], [stringMaxLength])

参数

  • table:要保存的内存表。
  • fileName:HDF5文件名,类型为字符串标量。
  • datasetName:dataset名称,即表名。可通过ls或lsTable获得,类型为字符串标量。
  • append:是否追加数据到已存在dataset。类型为布尔型,默认为false。
  • stringMaxLength:字符串最大长度,类型为数值类型,默认为16。仅对table中的string和symbol类型起作用。

详情

将DolphinDB数据库的内存表保存到HDF5文件中的指定数据集。支持的数据类型,以及数据转化规则可见支持的数据类型章节。

例子

hdf5::saveHDF5(tb, "example.h5", "dataset name in hdf5")

注意

  • HDF5文件中无法存入空值。若DolphinDB表中存在空值,会按照支持的数据类型中的默认值存入。
  • 若需通过python读取由HDF5插件生成的h5文件,需要使用通过h5py库进行读取。例如:
    import h5py
    f = h5py.File("/home/workDir/dolphindb_src/build/test.h5", 'r')
    print(f['aaa']['TimeStamp'])
    print(f['aaa']['StockID'])

支持的数据类型

浮点和整数类型会被先转换为H5T_NATIVE_*类型。

integer

Type in HDF5Default Value in HDF5Type in CType in DolphinDB
H5T_NATIVE_CHAR‘\0’signed char / unsigned charchar/short
H5T_NATIVE_SCHAR‘\0’signed charchar
H5T_NATIVE_UCHAR‘\0’unsigned charshort
H5T_NATIVE_SHORT0shortshort
H5T_NATIVE_USHORT0unsigned shortint
H5T_NATIVE_INT0intint
H5T_NATIVE_UINT0unsigned intlong
H5T_NATIVE_LONG0longint/long
H5T_NATIVE_ULONG0unsigned longunsupported/long
H5T_NATIVE_LLONG0long longlong
H5T_NATIVE_ULLONG0unsigned long longunsupported/long
  • DolphinDB中数值类型都为有符号类型。为了防止溢出,除64位无符号类型外,所有无符号类型会被转化为高一阶的有符号类型。特别的,64位无符号类型转化为64位有符号类型,若发生溢出则返回64位有符号类型的最大值。

  • H5T_NATIVE_CHAR 对应C中的char类型,而char是否有符号依赖与编译器及平台。若有符号依赖,则在DolphinDB中转化为char,否则为short。

  • H5T_NATIVE_LONG 以及 H5T_NATIVE_ULONG 对应C中的long类型。

  • 所有整数类型皆可以转化为DolphinDB中的数值类型(bool, char, short, int, long, float, double),若进行转化会发生溢出。例如LONG->INT会返回一个int的最值。

float

Type in HDF5Default Value in HDF5Type in CType in DolphinDB
H5T_NATIVE_FLOAT+0.0ffloatfloat
H5T_NATIVE_DOUBLE+0.0doubledouble

注意 :IEEE754浮点数类型皆为有符号数。

  • 所有浮点数类型皆可以转化为DolphinDB中的数值类型(bool, char, short, int, long, float, double),若进行转化会发生溢出。例如DOUBLE->FLOAT会返回一个float的最值。

time

type in hdf5Default Value in HDF5corresponding c typecorresponding dolphindb type
H5T_UNIX_D32BE1970.01.01T00:00:004 bytes integerDT_TIMESTAMP
H5T_UNIX_D32LE1970.01.01T00:00:004 bytes integerDT_TIMESTAMP
H5T_UNIX_D64BE1970.01.01T00:00:00.0008 bytes integerDT_TIMESTAMP
H5T_UNIX_D64LE1970.01.01T00:00:00.0008 bytes integerDT_TIMESTAMP
  • HDF5预定义的时间类型为32位或者64位的posix时间。HDF5的时间类型缺乏官方的定义,在此插件中,32位时间类型代表距离1970年的秒数,而64位则精确到毫秒。所有时间类型会被插件统一转化为一个64位整数,然后转化为DolphinDB中的timestamp类型。

  • 以上类型皆可以转化为DolphinDB中的时间相关类型(date, month, time, minute, second, datetime, timestamp, nanotime, nanotimestamp)。

string

type in hdf5Default Value in HDF5corresponding c typecorresponding dolphindb type
H5T_C_S1“”char*DT_STRING
  • H5T_C_S1包括固定长度(fixed-length)字符串和可变长度(variable-length)字符串。
  • string类型可以转化为DolphinDB中的字符串相关类型(string, symbol)。

enum

type in hdf5corresponding c typecorresponding dolphindb type
ENUMenumDT_SYMBOL
  • 枚举类型会被转化为DolphinDB中的一个symbol变量。请注意,每个字符串所对应的枚举值以及大小关系并不会被保存。例如,枚举类型 HDF5_ENUM{"a"=100,"b"=2000,"c"=30000}可能会被转化为 SYMBOL{"a"=3,"b"=1"c"=2}。
  • enum类型可以转化为DolphinDB中的字符串相关类型(string, symbol)。

compound and array

type in hdf5corresponding c typecorresponding dolphindb type
H5T_COMPOUNDstruct\
H5T_ARRAYarray\
  • 复合(compound)类型以及数组(array)类型只要不包含不支持的类型,就可以被解析,而且支持嵌套。
  • 复杂类型的转化取决于其内部子类型。

表结构

简单类型

简单类型导入DolphinDB后的table与HDF5文件中的table完全一致。

HDF5中的简单类型表

12
1int(10)int(67)
2int(20)int(76)

导入DolphinDB后的简单类型表

col_1col_2
11067
22076

复杂类型

复杂类型导入DolphinDB后的类型取决于复杂类型的结构。

HDF5中的复合类型表

12
1structstruct
2structstruct

导入DolphinDB后:

abc
1123.7
2112131.7
3122232.7
4132333.7

HDF5中的数组类型表

12
1array(1,2,3)array(4,5,6)
2array(8,9,10)array(15,16,17)

导入DolphinDB后:

array_1array_2array_3
1123
2456
38910
4151617

HDF5中的嵌套类型表

对嵌套的复杂类型,结果中会添加'A'前缀代表数组,'C'前缀代表复合类型。

12
1struct{a:array(1,2,3) b:2 c:struct{d:"abc"}}struct{a:array(7,8,9) b:5 c:struct{d:"def"}}
2struct{a:array(11,21,31) b:0 c:struct{d:"opq"}}struct{a:array(51,52,53) b:24 c:struct{d:"hjk"}}

导入DolphinDB后:

Aa_1Aa_2Aa_3bCc_d
11232abc
27895def
31121310opq
451525324hjk

性能

环境

  • CPU: i7-7700 3.60GHZ
  • SSD: 连续读取 最多每秒460~500MB

数据集导入性能

  • 单一类型(int)
    • 行数 1024 * 1024 * 16
    • 列数 64
    • 文件大小 4G
    • 耗时 8秒
  • 单一类型(unsigned int)
    • 行数 1024 * 1024 * 16
    • 列数 64
    • 文件大小 4G
    • 耗时 9秒
  • 单一类型(variable-length string)
    • 行数 1024 * 1024
    • 列数 64
    • 文件大小 3.6G
    • 耗时 17秒
  • 复合类型
    • 子类型共9列:(str,str,double,int,long,float,int,short,char)
    • 行数 1024 * 1024 * 62
    • 文件大小 3.9G
    • 耗时 10秒
  • 数组复合类型
    • 子类型共72列:(str,str,double,int,long,float,int,short,char) * 8
    • 行数 1024 * 128 * 62
    • 文件大小 3.9G
    • 耗时 15秒

附录:预编译安装(可选)

如果不通过插件市场安装插件,也可以预编译安装方式完成插件安装。

导入 DolphinDB 安装包中或者bin目录下预编译好的 HDF5 插件。

Linux

(1) 添加插件所在路径到LIB搜索路径 LD_LIBRARY_PATH

export LD_LIBRARY_PATH=/path_to_hdf5_plugin/:$LD_LIBRARY_PATH

(2) 启动DolphinDB server并导入插件

loadPlugin("/path_to_hdf5_plugin/PluginHdf5.txt")

Windows

必须通过绝对路径加载,且路径中使用"\\"或"/"代替"\"。

loadPlugin("path_to_hdf5_plugin/PluginHdf5.txt")

编译安装

可使用以下方法编译 HDF5 插件,编译成功后通过以上方法导入。

在 Linux 下安装

安装cmake:

sudo apt install cmake

编译c-blosc

#在https://github.com/Blosc/c-blosc/releases/tag/v1.21.1 下载源码
cd c-blosc-1.21.1
mkdir build
cd build
cmake -DCMAKE_C_FLAGS="-fPIC -std=c11" ..
make -j
cp blosc/src/blosc.h /path_to_hdf5_plugin/include/c-blosc
cp blosc/src/blosc-export.h /path_to_hdf5_plugin/include/c-blosc
cp blosc/libblosc.a /path_to_hdf5_plugin/lib

编译HDF5 1.13.1:

# git clone https://github.com/HDFGroup/hdf5/ -b hdf5-1_13_1
# 若您不熟悉插件源代码,请不要下载其他版本,hdf5版本兼容性差,可能导致安装失败
cd hdf5-1.13.1
export CC=gcc-4.8
export CXX=g++-4.8
export CFLAGS="-fPIC -std=c11"
export CXXFLAGS="-fPIC -std=c++11"
./configure --enable-cxx
make
make check
make install
make check-install
cp hdf5/include/* /path_to_hdf5_plugin/include/
cp hdf5/lib/libhdf5.a /path_to_hdf5_plugin/lib
cp hdf5/lib/libhdf5_cpp.a /path_to_hdf5_plugin/lib
cp hdf5/lib/libhdf5_hl.a /path_to_hdf5_plugin/lib

编译整个项目:

mkdir build
cd build
cp /path_to_dolphindb/libDolphinDB.so ./
cmake ..
make

在 Windows 下安装

在 msys2 环境下,使用mingw 编译 hdf5 1.13.1.zip

  • 使用 mingw-w64-x86_64 编译器

    export PATH=/PATH_to mingw-w64/x86_64-5.3.0-win32-seh-rt_v4-rev0/mingw64/bin/:$PATH
  • 安装 make

    pacman -S make
  • 打开 msys2 终端,进入已经解压好的 hdf5-1.13.1 所在目录

     CFLAGS="-std=c11" CXXFLAGS="-std=c++11" ./configure --host=x86_64-w64-mingw32 --build=x86_64-w64-mingw32 --prefix=/d/hdf5_1.13.1 --enable-cxx --enable-tests=no --enable-tools=no with_pthread=no
  • 打开 src/H5pubconf.h,在末尾添加以下宏定义

    #ifndef H5_HAVE_WIN32_API
    #define H5_HAVE_WIN32_API 1
    #endif
    
    #ifndef H5_HAVE_MINGW
    #define H5_HAVE_MINGW 1
    #endif
  • 开始编译

    make -j8
    + make install -j8
  • 拷贝编译文件到 hdf5 插件文件目录

    cp $HOME/hdf5/include/* /path_to_hdf5_plugin/include_win/hdf5
    cp $HOME/hdf5/lib/libhdf5.a /path_to_hdf5_plugin/build
    cp $HOME/hdf5/lib/libhdf5_cpp.a /path_to_hdf5_plugin/build
    cp $HOME/hdf5/lib/libhdf5_hl.a /path_to_hdf5_plugin/build
    cp $HOME/hdf5/lib/libhdf5_hl_cpp.a /path_to_hdf5_plugin/build
  • 打开Windows的 CMD 命令行终端

  • 编译 c_blosc

    cd c_blosc-1.21.1
    mkdir build
    cd build
    cmake  ../ -G "MinGW Makefiles"
    mingw32-make -j8
    copy .\blosc\libblosc.a /path_to_hdf5_plugin\build\
  • 复制 libDolphinDB.dll 到 hdf5 编译目录

    copy /path_to_dolphindb/libDolphinDB.dll /path_to_hdf5_plugin/build
  • hdf5 插件编译

    cmake  ../ -G "MinGW Makefiles"
    mingw32-make -j