Configuring the Trino Hive Connector for GeoParquet

To query GeoParquet with Trino, create a Hive-connector catalog properties file that points at a metastore and your object storage, then declare an external table with the geometry column typed varbinary and a materialised bounding box for pruning. That is the whole setup: catalog file, metastore, DDL, and a few session properties to keep pushdown on. This page is the property-level companion to the Trino & Presto GeoParquet connector guide, which covers the query patterns those settings unlock.

Quick-Reference: Key Properties and DDL

Setting Where it lives Purpose Primary use case
connector.name=hive catalog .properties Selects the Hive connector Any GeoParquet-in-bucket table
hive.metastore.uri catalog .properties Locates table/partition metadata Thrift HMS deployments
hive.parquet.use-column-names=true catalog .properties Match columns by name, not ordinal Schemas that evolve upstream
geometry varbinary table DDL Holds WKB for ST_GeomFromBinary Every GeoParquet table
external_location table DDL Points at the S3/GCS prefix Read-only lake tables
parquet_max_read_block_size session Tune read granularity to row groups Wide analytical scans

The Catalog Properties File

A Trino catalog is nothing more than a properties file in etc/catalog/ on every node. The filename becomes the catalog name, so geo.properties creates a catalog you reference as geo.schema.table. The file selects the connector and hands it the two things it cannot guess: where the metastore is, and how to reach object storage.

markup
# etc/catalog/geo.properties — Trino 400+
connector.name=hive

# --- Metastore: resolves table + partition metadata ---
hive.metastore=thrift
hive.metastore.uri=thrift://hms.internal:9083

# --- Object storage (native S3 filesystem) ---
fs.native-s3.enabled=true
s3.region=us-west-2
s3.endpoint=https://s3.us-west-2.amazonaws.com
s3.path-style-access=false

# --- Parquet reader behaviour ---
hive.parquet.use-column-names=true      # match geometry by name, not ordinal
parquet.use-bloom-filter=true           # honour bloom filters if present
hive.parquet.max-read-block-size=16MB   # default read granularity

Two properties earn special attention for GeoParquet. hive.parquet.use-column-names=true matches columns by name rather than position, so a geometry column reordered or added by an upstream writer still binds correctly — ordinal matching silently reads the wrong column when schemas drift. parquet.use-bloom-filter=true lets Trino honour bloom filters on high-cardinality attribute columns (parcel IDs, feature keys), which complements the row-group pruning that the bounding-box columns provide. Because Trino reads catalog files at startup, changing this file needs a node restart unless you run with dynamic catalog management.

The Metastore and External Location

The Hive connector needs a metastore, but not a Hadoop cluster. A standalone Thrift Hive Metastore backed by a small PostgreSQL or MySQL database is enough, and AWS Glue works as a drop-in via hive.metastore=glue. The metastore stores the table schema, the external location, and the partition list; the data itself stays in your bucket. Declaring external_location in the DDL (rather than a managed location) tells Trino the files are read-only and owned outside the catalog, so a DROP TABLE removes only metadata, never the objects.

Table DDL for WKB Geometry

The DDL declares the geometry column as varbinary — Trino’s type for the Parquet BYTE_ARRAY that GeoParquet uses for WKB — and, critically, materialises a bounding box as four double columns. Those numeric columns are what give spatial queries real pushdown: their min/max statistics prune row groups by extent, which the opaque geometry column can never do. This is the same locality-encoding idea explored in spatial partitioning with quadtree indexes.

sql
-- Trino Hive connector external table over GeoParquet
CREATE TABLE geo.spatial.parcels (
    parcel_id   varchar,
    land_use    varchar,
    assessed    double,
    xmin        double,      -- bounding box for row-group pruning
    ymin        double,
    xmax        double,
    ymax        double,
    geometry    varbinary,   -- WKB decoded via ST_GeomFromBinary
    region      varchar      -- partition column (lives in the path)
)
WITH (
    external_location = 's3://geo-lake/parcels/',
    format = 'PARQUET',
    partitioned_by = ARRAY['region']
);

-- If partitions already exist under the prefix, register them:
CALL geo.system.sync_partition_metadata(
    schema_name => 'spatial',
    table_name  => 'parcels',
    mode        => 'FULL'
);

The sync_partition_metadata procedure walks the prefix and registers every region=... path, the Hive-connector equivalent of MSCK REPAIR. Run it after each bulk load, or automate it in your ingest job. Pair the writer’s row-group size with the row group sizing strategies for Parquet guidance so splits land evenly across workers.

Session Properties for Pushdown

Catalog properties set defaults; session properties tune a single query without a restart. Keep pushdown on and match the read block size to your row groups.

sql
-- Per-session tuning; scope is the current connection only
SET SESSION geo.parquet_max_read_block_size = '32MB';   -- wider scans
SET SESSION geo.projection_pushdown_enabled = true;      -- default; keep on
-- Confirm predicate + projection pushdown in the plan:
EXPLAIN (TYPE DISTRIBUTED)
SELECT parcel_id FROM geo.spatial.parcels
WHERE region = 'us-west' AND xmin > -123 AND xmax < -121;

Raising parquet_max_read_block_size helps large sequential scans read fewer, bigger chunks; lowering split concurrency helps memory-tight federated joins. None of these touch the spatial predicate — ST_Intersects always runs in the engine after decode — so the goal of every setting here is simply to shrink how much data reaches that stage.

Validation

Confirm the catalog loaded and pushdown is active before trusting query costs:

sql
SHOW CATALOGS;                              -- 'geo' should appear
SHOW TABLES FROM geo.spatial;               -- 'parcels' should appear
EXPLAIN ANALYZE
SELECT count(*) FROM geo.spatial.parcels
WHERE region = 'us-west' AND xmin > -123 AND xmax < -121;

In the EXPLAIN ANALYZE output, check the TableScan node: a large gap between “input rows” and rows emitted means row-group pruning is working, and a small “physical input” byte count confirms projection pushdown dropped unused columns. If physical input equals the whole partition, the bounding-box predicate is not pruning — verify the xmin..ymax columns carry statistics (they do when written by any standard Parquet writer with write_statistics=True).

Edge Cases and Caveats

Glue instead of Thrift. Setting hive.metastore=glue swaps the metastore backend but keeps the DDL identical. Glue enforces per-table partition limits, so very large partition counts still favour a partitioning scheme that keeps paths bounded, as covered for the serverless case in partitioning GeoParquet for Athena cost control.

MinIO and non-AWS S3. For MinIO or other S3-compatible stores, set s3.path-style-access=true and an explicit s3.endpoint; virtual-host addressing usually fails against these. Credentials come from s3.aws-access-key/s3.aws-secret-key or an instance role.

Missing statistics after external writes. If GeoParquet files were written without column statistics, row-group pruning silently does nothing. Rewrite them through a writer that emits statistics, or run ANALYZE geo.spatial.parcels so Trino gathers table-level stats for the cost-based optimiser.

Frequently Asked Questions

Where do Trino catalog properties files live?

In the etc/catalog directory of every coordinator and worker, one properties file per catalog, named for the catalog it creates. A file called geo.properties produces a catalog named geo. On container deployments the directory is usually mounted or baked into the image, and Trino reads it at startup, so adding or changing a catalog requires a restart unless dynamic catalog management is enabled.

Do I need a Hive metastore to query GeoParquet with Trino?

The Hive connector needs a metastore for table and partition metadata: either a standalone Thrift Hive Metastore or AWS Glue. It does not require a running Hadoop cluster. If you would rather avoid a metastore entirely, use a table-format connector like Iceberg or Delta Lake whose metadata lives with the data, but for plain GeoParquet files the Hive connector plus a lightweight metastore is the standard setup.

Which session properties matter most for GeoParquet pushdown?

Keep predicate and projection pushdown enabled so partition and column filters reach storage, and tune the Parquet read block size to match your row-group size. Session scope lets you raise the read block size for wide scans or lower split concurrency for memory-tight federated joins without editing the catalog file. The spatial ST_ predicate is unaffected by these — it always runs in the engine after decode.


← Back to Trino & Presto GeoParquet Connector