PostgreSQL Backend
The PostgreSQL backend provides optimal performance for FilterMate, especially with large datasets. It leverages server-side spatial operations, materialized views, and spatial indexes for ultra-fast filtering.
PostgreSQL is recommended for datasets > 50,000 features and required for datasets > 500,000 features.
Overviewβ
FilterMate's PostgreSQL backend connects directly to your PostGIS-enabled database to perform geometric filtering operations server-side. This approach dramatically reduces data transfer and processing time compared to client-side filtering.
Key Benefitsβ
- β‘ Sub-second queries on million+ feature datasets
- π§ Materialized views for persistent filtered results
- πΊοΈ GIST spatial indexes for optimized spatial searches
- π Server-side processing reduces network overhead
- πΎ Memory efficient - processes data in the database
- βοΈ Concurrent operations - multiple filters don't slow down
When PostgreSQL Backend Is Usedβ
FilterMate automatically selects the PostgreSQL backend when:
- β Layer source is PostgreSQL/PostGIS
- β
psycopg2Python package is installed - β Database connection is available
If psycopg2 is not installed, FilterMate falls back to Spatialite or OGR backends with a performance warning for large datasets.
Installationβ
Prerequisitesβ
- PostgreSQL 9.5+ with PostGIS 2.3+ extension
- QGIS 3.x with PostgreSQL connection configured
- Python 3.7+ (included with QGIS)
Installing psycopg2β
Choose the method that works best for your environment:
Method 1: pip (Recommended)β
pip install psycopg2-binary
Method 2: QGIS Python Consoleβ
Open QGIS Python Console (Ctrl+Alt+P) and run:
import pip
pip.main(['install', 'psycopg2-binary'])
Method 3: OSGeo4W Shell (Windows)β
# Open OSGeo4W Shell as Administrator
py3_env
pip install psycopg2-binary
Method 4: Conda (if using conda environment)β
conda install -c conda-forge psycopg2
Verificationβ
Check if psycopg2 is available:
# In QGIS Python Console
try:
import psycopg2
print(f"β psycopg2 version: {psycopg2.__version__}")
except ImportError:
print("β psycopg2 not installed")
Featuresβ
1. Materialized Viewsβ
FilterMate creates materialized views in PostgreSQL to store filtered results persistently:
-- Example materialized view created by FilterMate
CREATE MATERIALIZED VIEW filtermate_filtered_view_123 AS
SELECT *
FROM my_layer
WHERE ST_Intersects(
geometry,
(SELECT geometry FROM filter_layer WHERE id = 1)
);
-- Spatial index automatically created
CREATE INDEX idx_filtermate_filtered_view_123_geom
ON filtermate_filtered_view_123
USING GIST (geometry);
Benefits:
- Results cached in database
- Instant refresh on subsequent filters
- Shareable across QGIS sessions
- Automatic cleanup on plugin close
2. Server-Side Spatial Operationsβ
All geometric operations execute in the database:
ST_Intersects()- Find intersecting featuresST_Contains()- Find containing featuresST_Within()- Find features within boundariesST_Buffer()- Create buffers server-sideST_Distance()- Calculate distances
Performance Impact:
| Operation | Client-Side (Python) | Server-Side (PostGIS) |
|---|---|---|
| 10k features | ~5 seconds | ~0.5 seconds (10x faster) |
| 100k features | ~60 seconds | ~2 seconds (30x faster) |
| 1M features | Timeout/crash | ~10 seconds (100x+ faster) |
3. GIST Spatial Indexesβ
FilterMate ensures your geometries have GIST indexes for optimal query performance:
-- Check existing indexes
SELECT indexname, indexdef
FROM pg_indexes
WHERE tablename = 'my_layer';
-- FilterMate creates GIST indexes automatically
CREATE INDEX IF NOT EXISTS idx_my_layer_geom
ON my_layer
USING GIST (geometry);
FilterMate checks for spatial indexes and creates them if missing. This one-time operation may take a few seconds on large tables.
4. Query Optimizationβ
The PostgreSQL backend applies several optimizations:
- Bounding box pre-filtering - Uses
&&operator before expensive operations - Parallel query execution - Leverages PostgreSQL's parallel workers
- Prepared statements - Reuses query plans for repeated filters
- ANALYZE statistics - Ensures optimal query planning
Example optimized query:
-- Bounding box filter first (fast)
WHERE geometry && ST_Buffer(filter_geom, 100)
-- Then expensive intersection check (only on bbox matches)
AND ST_Intersects(geometry, ST_Buffer(filter_geom, 100))
Configurationβ
Database Connectionβ
FilterMate uses QGIS's existing PostgreSQL connection. Ensure your connection is configured:
- Layer β Data Source Manager β PostgreSQL
- New connection with details:
- Name:
my_postgis_db - Host:
localhost(or remote host) - Port:
5432 - Database:
my_database - Authentication: Basic or stored credentials
- Name:
Performance Settingsβ
Optimize PostgreSQL for spatial queries:
-- In postgresql.conf or per-session
-- Increase work memory for large sorts
SET work_mem = '256MB';
-- Enable parallel query execution
SET max_parallel_workers_per_gather = 4;
-- Optimize for spatial operations
SET random_page_cost = 1.1; -- For SSD storage
Schema Permissionsβ
FilterMate requires these PostgreSQL permissions:
-- Minimum required permissions
GRANT CONNECT ON DATABASE my_database TO filter_mate_user;
GRANT USAGE ON SCHEMA public TO filter_mate_user;
GRANT SELECT ON ALL TABLES IN SCHEMA public TO filter_mate_user;
GRANT CREATE ON SCHEMA public TO filter_mate_user; -- For temp views
Usageβ
Basic Filteringβ
- Load PostgreSQL layer in QGIS
- Open FilterMate plugin
- Configure filter options
- Click "Apply Filter"
FilterMate automatically:
- Detects PostgreSQL backend
- Creates materialized view
- Adds filtered layer to QGIS
- Displays backend indicator: [PG]
Advanced Optionsβ
Custom Schemaβ
Specify custom schema for materialized views:
# In config/config.json
{
"POSTGRESQL": {
"schema": "filtermate_temp",
"auto_cleanup": true
}
}
Connection Poolingβ
For multiple simultaneous filters:
# FilterMate handles connection pooling automatically
# Max connections: 5 (configurable)
Performance Tuningβ
For Small Datasets (< 10k features)β
- No special configuration needed
- PostgreSQL performs similarly to Spatialite
- Use default settings
For Medium Datasets (10k - 100k features)β
- Ensure spatial indexes exist
- Increase
work_memto 128MB - Enable parallel workers (2-4)
ALTER TABLE my_layer SET (parallel_workers = 2);
For Large Datasets (100k - 1M features)β
- Increase
work_memto 256MB+ - Increase
parallel_workersto 4-8 - Run
VACUUM ANALYZEregularly
VACUUM ANALYZE my_layer;
For Very Large Datasets (> 1M features)β
- Partition tables by spatial extent
- Use table inheritance
- Consider table clustering by geometry
-- Cluster table by spatial index
CLUSTER my_layer USING idx_my_layer_geom;
Troubleshootingβ
Issue: "psycopg2 not found"β
Symptom: FilterMate shows OGR/Spatialite backend for PostgreSQL layers
Solution:
- Install psycopg2 (see Installation section)
- Restart QGIS
- Verify installation in Python Console
Issue: "Permission denied to create view"β
Symptom: Error when applying filter
Solution:
-- Grant CREATE permission
GRANT CREATE ON SCHEMA public TO your_user;
-- Or use a dedicated schema
CREATE SCHEMA filtermate_temp;
GRANT ALL ON SCHEMA filtermate_temp TO your_user;
Issue: "Slow queries despite PostgreSQL"β
Symptom: Queries take longer than expected
Solution:
-
Check for spatial indexes:
SELECT * FROM pg_indexes WHERE tablename = 'your_table'; -
Run ANALYZE:
ANALYZE your_table; -
Check query plan:
EXPLAIN ANALYZE
SELECT * FROM your_table
WHERE ST_Intersects(geometry, ST_GeomFromText('POLYGON(...)')); -
Look for "Seq Scan" - if present, index not being used
Issue: "Connection timeout"β
Symptom: FilterMate hangs when applying filter
Solution:
- Increase PostgreSQL
statement_timeout - Check network connectivity
- Verify database server is responsive
-- Increase timeout to 5 minutes
SET statement_timeout = '300s';
Performance Benchmarksβ
Real-world performance on typical hardware (Core i7, 16GB RAM, SSD):
| Dataset Size | Features | PostgreSQL | Spatialite | Speedup |
|---|---|---|---|---|
| Small | 5,000 | 0.3s | 0.4s | 1.3x |
| Medium | 50,000 | 1.2s | 8.5s | 7x |
| Large | 500,000 | 8.4s | 65s | 8x |
| Very Large | 5,000,000 | 45s | Timeout | 10x+ |
Spatial Operations:
| Operation | 100k Features | 1M Features |
|---|---|---|
| Intersects | 1.5s | 9.2s |
| Contains | 1.8s | 11.5s |
| Buffer (10m) + Intersects | 2.3s | 15.1s |
| Complex expression | 3.1s | 18.7s |
Best Practicesβ
β Doβ
- Use PostgreSQL for datasets > 50k features
- Ensure spatial indexes exist before filtering
- Run VACUUM ANALYZE after bulk data updates
- Use connection pooling for multiple filters
- Monitor query performance with EXPLAIN
β Don'tβ
- Don't mix spatial reference systems - reproject beforehand
- Don't create too many materialized views - FilterMate auto-cleans up
- Don't disable spatial indexes - huge performance penalty
- Don't run complex expressions without testing - use EXPLAIN first
See Alsoβ
- Backends Overview - Multi-backend architecture
- Backend Selection - Automatic selection logic
- Performance Comparison - Detailed benchmarks
- Spatialite Backend - Alternative for smaller datasets
- Troubleshooting - Common issues
Technical Detailsβ
Connection Managementβ
FilterMate uses psycopg2 for database connections:
import psycopg2
from qgis.core import QgsDataSourceUri
# Extract connection from QGIS layer
uri = QgsDataSourceUri(layer.source())
conn = psycopg2.connect(
host=uri.host(),
port=uri.port(),
database=uri.database(),
user=uri.username(),
password=uri.password()
)
Materialized View Lifecycleβ
- Creation - When filter applied
- Usage - QGIS loads as virtual layer
- Refresh - On filter parameter change
- Cleanup - On plugin close or manual cleanup
Supported PostGIS Functionsβ
FilterMate translates QGIS expressions to PostGIS functions:
| QGIS Expression | PostGIS Function |
|---|---|
intersects() | ST_Intersects() |
contains() | ST_Contains() |
within() | ST_Within() |
buffer() | ST_Buffer() |
distance() | ST_Distance() |
area() | ST_Area() |
length() | ST_Length() |
Last Updated: December 8, 2025
Plugin Version: 2.2.3
PostgreSQL Support: 9.5+ with PostGIS 2.3+