Skip to content

Pre-release documentation

This describes Beacon 2.0.0-rc3, a release candidate. Behavior documented here may still change before 2.0.0 ships, and some of it is not in any released build yet. For the current stable release, see the 1.8.0 documentation.

HDF5

sql
SELECT * FROM read_hdf5('experiments/**/*.h5') LIMIT 10;

Beacon recognizes .h5 and .hdf5. It finds them in the dataset store automatically.

Two readers

A netCDF-4 file is an HDF5 file, and the netCDF-c library also opens plain HDF5. Beacon reads HDF5 through the pure-Rust reader by default. Beacon reads it through that library when you set the Rust reader to false. HDF5 behaves exactly like NetCDF: the same data model, the same array to table mapping, the same CF decoding and the same attribute columns.

The pure-Rust HDF5 reader is the default. It reads the same files and gives the same answer for a netCDF-4 file, and it adds five things over netCDF-c:

netCDF-cPure-Rust reader (default)
Nested groupsRoot group onlyEvery group
Compound datasetsNot readOne column for each member
Object storageAnonymous access onlyFull credential chain, no local copy
File statisticsNonePer-file column ranges
Concurrent scansOne file at a timeIn parallel
WritesnetCDF-cnetCDF-c

The flag is on by default, and it is separate from BEACON_NETCDF_USE_RUST_READER, so you move one format at a time. Set it for one table instead of the whole server:

sql
CREATE EXTERNAL TABLE experiments
STORED AS HDF5
LOCATION 'experiments/'
OPTIONS ('use_rust_reader' 'false');

How a dataset becomes a column

An HDF5 dataset reads as a variable. An HDF5 attribute reads as a <dataset>.<attribute> column, and a file attribute as .<attribute>.

The pure-Rust reader adds two more shapes. Both use /, so quote the column name in SQL.

A dataset inside a group

A dataset outside the root group keeps its path as its column name. Two groups can then hold the same name without a collision.

text
/                       .title
  station_id            station_id
  observations/         observations/.units
    temperature         observations/temperature
    qc/
      flag              observations/qc/flag
sql
SELECT station_id, "observations/temperature", "observations/qc/flag"
FROM read_hdf5('nested.h5');

A group attribute takes the group's path and the leading dot: observations/.units.

A compound dataset

An HDF5 compound dataset holds a record in each element, the way a table row holds columns. Each member becomes its own column, named <dataset>/<member>. The columns share the dataset's shape, so a query joins them by row the way it joins two ordinary datasets.

sql
SELECT "measurements/station", "measurements/depth", "measurements/label"
FROM read_hdf5('compound.h5');

Beacon reads a member of a fixed-width numeric or string type. It skips a member that holds a pointer into a heap — a variable-length string, a nested compound, an array — and logs the dataset and every member type. A compound whose members are all of that kind gives no columns, and the log names it.

Read one file, a glob or a list

sql
-- one file
SELECT * FROM read_hdf5('experiments/run-01.h5');

-- every level below a directory
SELECT * FROM read_hdf5('experiments/**/*.h5');

-- an explicit list
SELECT * FROM read_hdf5(['a.h5', 'b.hdf5']);

Select the dimensions

Like NetCDF, read_hdf5 takes an optional second argument: the dimensions to read. It sets the grid, and Beacon returns a dataset only if the list holds all of that dataset's dimensions.

sql
SELECT * FROM read_hdf5(['experiments/**/*.h5'], ['sample', 'channel']);

A netCDF-4 file names its axes with HDF5 dimension scales, and Beacon uses those names. A plain HDF5 file attaches no scales, so Beacon names the axes phony_dim_0, phony_dim_1 and so on, one for each axis. Two datasets of the same rank then share those names and broadcast together.

See Arrays to tables.

Inspect the schema

Check the columns and the types before you write a query:

sql
SELECT * FROM read_hdf5_schema('experiments/**/*.h5');

Inspect a schema compares the _schema functions, SUMMARIZE, DESCRIBE and LIMIT 0, and says what each one costs.

As an external table

sql
CREATE EXTERNAL TABLE experiments
STORED AS HDF5
LOCATION 'experiments/';

STORED AS H5 is accepted as a synonym.

On object storage

On the netCDF-c reader, HDF5 supports anonymous access only, for the same reason as NetCDF: that library opens a file by URL and does not go through the credential chain. For a public bucket, set AWS_SKIP_SIGNATURE=true.

The default pure-Rust reader has no such limit. It reads byte ranges through the object store, so a private S3, GCS or Azure bucket works and no local copy is made. A bucket needs no option at all:

sql
CREATE EXTERNAL TABLE experiments
STORED AS HDF5
LOCATION 's3://bucket/experiments/';

See Object Storage.

As a query output

COPY TO ... STORED AS HDF5 uses the netCDF-4 writer. The result is a netCDF-4 file with an HDF5 extension. Every HDF5 reader opens it. A write always uses netCDF-c, whatever the read flag says.

What does not map

The pure-Rust reader covers nested groups and compound datasets. It does not read a variable-length or opaque type, a reference, or a region reference.

On the netCDF-c reader the netCDF data model bounds what Beacon sees. A compound datatype, a variable-length or opaque type, a reference, and a group outside the root are not read.

One more limit is worth knowing. Beacon drops an attribute narrower than 8 bytes on a file written with the earliest HDF5 library version — h5py's default — because the reader takes the object header padding as part of the value. The datasets are unaffected. This is an upstream defect; a netCDF-4 file never meets it.

See also

Released under the AGPL-3.0 License.