Skills DirectorySkills Directory
SkillsLearnSecurityCategoriesDocsBlogPro
Sign InSubmit Skill
Skills Directory

Security-tested agent skills for Claude, coding agents, and AI workflows.

Directory

  • Browse Skills
  • All Skills Aโ€“Z
  • Claude Skills
  • Claude Code Skills
  • Agent Skills
  • Categories
  • Authors
  • Submit a Skill

Learn

  • Learn Hub
  • Install Claude Skills
  • Write SKILL.md
  • Skills vs MCP
  • Directories Compared

Security

  • Security
  • Methodology
  • Secure Claude Skills
  • Security Badges
  • Chrome Extension
  • Skill Manager

Company

  • About
  • Community
  • Blog
  • API Docs
  • Advertise

2026 Skills Directory. All rights reserved.

ProTermsPrivacyRefunds
Back to skills

Postgres Optimization

ASecurity

Unconventional PostgreSQL optimization techniques

56 stars
0 votes
0 copies
0 views
Added 10/6/2026
databasesgosqlexpressdebuggingapidatabaseperformance

Works with

terminalapi

Security Analysis

A100/100

Pro scans all 6 files and shows the line behind each finding

Scanned 10/6/2026

$npx -y skills add SimHacker/moollm --skill postgres-optimization --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Postgres Optimization?

Add the live security badge to your README โ€” it updates automatically with every re-scan.

Security grade badge for Postgres Optimization
[![Security: A โ€” Skills Directory](https://www.skillsdirectory.com/api/skills/simhacker-postgres-optimization/badge)](https://www.skillsdirectory.com/skills/simhacker-postgres-optimization)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
Files
SKILL.md
---
name: postgres-optimization
description: Unconventional PostgreSQL optimization techniques
license: MIT
tier: 2
allowed-tools:
  - read_file
  - write_file
  - run_terminal_cmd
  - grep
related: [postgres, debugging, plan-then-execute, robust-first]
tags: [moollm, database, postgres, performance, optimization, indexing]
inputs:
  query:
    type: string
    required: false
    description: "Query to optimize"
  table:
    type: string
    required: false
    description: "Table to analyze"
outputs:
  - OPTIMIZATION.md
  - EXPLAIN-ANALYSIS.txt
credits:
  source:
    title: "Unconventional PostgreSQL Optimizations"
    author: "Haki Benita"
    url: "https://hakibenita.com/postgres-unconventional-optimizations"
---

# ๐Ÿ˜ PostgreSQL Optimization

> **"Beyond 'just add an index' โ€” creative solutions for real performance problems."**

Unconventional optimization techniques for PostgreSQL that go beyond standard DBA playbooks.

## Purpose

When conventional approaches fall short โ€” query rewrites, adding indexes, VACUUM, ANALYZE โ€” these techniques offer creative solutions:

- Eliminate impossible query scans with constraint exclusion
- Reduce index size with function-based indexes
- Enforce uniqueness with hash indexes instead of B-Trees

## When to Use

- Ad-hoc query environments where users make mistakes
- Large indexes approaching table size
- Uniqueness constraints on large text values (URLs, documents)
- Timestamp columns queried at coarser granularity

---

## Technique 1: Constraint Exclusion

### The Problem

Check constraints prevent invalid data, but PostgreSQL doesn't use them to optimize queries by default.

```sql
CREATE TABLE users (
    id INT PRIMARY KEY,
    username TEXT NOT NULL,
    plan TEXT NOT NULL,
    CONSTRAINT plan_check CHECK (plan IN ('free', 'pro'))
);
```

An analyst writes:

```sql
SELECT * FROM users WHERE plan = 'Pro';  -- Note: capital P
```

Despite the check constraint making this condition impossible, PostgreSQL scans the entire table.

### The Solution

```sql
SET constraint_exclusion TO 'on';
```

With constraint exclusion enabled:

```sql
EXPLAIN ANALYZE SELECT * FROM users WHERE plan = 'Pro';
```

```
Result  (cost=0.00..0.00 rows=0 width=0)
  One-Time Filter: false
Execution Time: 0.008 ms
```

PostgreSQL recognizes the condition contradicts the constraint and skips the scan entirely.

### When to Enable

| Environment | Recommendation |
|-------------|----------------|
| OLTP production | Leave as 'partition' (default) |
| BI / Data Warehouse | Set to 'on' |
| Ad-hoc query tools | Set to 'on' |
| Reporting databases | Set to 'on' |

### Tradeoffs

- **Benefit**: Eliminates impossible query scans
- **Cost**: Extra planning overhead evaluating constraints against conditions
- **Default**: 'partition' โ€” only used for partition pruning

---

## Technique 2: Function-Based Indexes for Lower Cardinality

### The Problem

You have a sales table with timestamps:

```sql
CREATE TABLE sale (
    id INT PRIMARY KEY,
    sold_at TIMESTAMPTZ NOT NULL,
    charged INT NOT NULL
);
```

Analysts query by day:

```sql
SELECT date_trunc('day', sold_at AT TIME ZONE 'UTC'), SUM(charged)
FROM sale
WHERE sold_at BETWEEN '2025-01-01 UTC' AND '2025-02-01 UTC'
GROUP BY 1;
```

You add a B-Tree index on `sold_at` โ€” 214 MB for a 160 MB table. The index is almost half the table size!

### The Solution

Index only what queries need:

```sql
CREATE INDEX sale_sold_at_date_ix 
ON sale((date_trunc('day', sold_at AT TIME ZONE 'UTC'))::date);
```

| Index | Size |
|-------|------|
| `sale_sold_at_ix` (full timestamp) | 214 MB |
| `sale_sold_at_date_ix` (date only) | 66 MB |

The function-based index is **3x smaller** because:
- Dates are 4 bytes vs 8 bytes for timestamptz
- Fewer distinct values enable deduplication

### The Discipline Problem

Function-based indexes require exact expression match:

```sql
-- Uses the index โœ“
WHERE date_trunc('day', sold_at AT TIME ZONE 'UTC')::date 
      BETWEEN '2025-01-01' AND '2025-01-31'

-- Does NOT use the index โœ—
WHERE (sold_at AT TIME ZONE 'UTC')::date 
      BETWEEN '2025-01-01' AND '2025-01-31'
```

### Solution: Virtual Generated Columns (PostgreSQL 18+)

```sql
ALTER TABLE sale ADD sold_at_date DATE
GENERATED ALWAYS AS (date_trunc('day', sold_at AT TIME ZONE 'UTC'));
```

Now queries use the virtual column:

```sql
SELECT sold_at_date, SUM(charged)
FROM sale
WHERE sold_at_date BETWEEN '2025-01-01' AND '2025-01-31'
GROUP BY 1;
```

**Benefits:**
- Smaller index
- Faster queries
- No discipline required โ€” column guarantees correct expression
- No ambiguity about timezones

**Limitation:** PostgreSQL 18 doesn't support indexes directly on virtual columns (yet).

---

## Technique 3: Hash Index for Uniqueness

### The Problem

You have a table with large URLs:

```sql
CREATE TABLE urls (
    id INT PRIMARY KEY,
    url TEXT NOT NULL,
    data JSON
);
```

You add a unique B-Tree index:

```sql
CREATE UNIQUE INDEX urls_url_unique_ix ON urls(url);
```

| Size |
|------|
| Table: 160 MB |
| B-Tree index: 154 MB |

The index is almost as large as the table because B-Tree stores actual values in leaf blocks.

### The Solution

Use an exclusion constraint with a hash index:

```sql
ALTER TABLE urls 
ADD CONSTRAINT urls_url_unique_hash 
EXCLUDE USING HASH (url WITH =);
```

| Index | Size |
|-------|------|
| B-Tree | 154 MB |
| Hash | 32 MB |

The hash index is **5x smaller** because it stores hash values, not the actual URLs.

### Uniqueness Is Enforced

```sql
INSERT INTO urls (id, url) VALUES (1000002, 'https://example.com');
-- ERROR: conflicting key value violates exclusion constraint
```

### Queries Still Fast

```sql
EXPLAIN ANALYZE SELECT * FROM urls WHERE url = 'https://example.com';
```

```
Index Scan using urls_url_unique_hash on urls
Execution Time: 0.022 ms  -- Faster than B-Tree's 0.046 ms!
```

### Limitations

| Feature | B-Tree Unique | Hash Exclusion |
|---------|--------------|----------------|
| Foreign key reference | โœ“ | โœ— |
| `ON CONFLICT (column)` | โœ“ | โœ— |
| `ON CONFLICT ON CONSTRAINT` | โœ“ | โœ“ (DO NOTHING only) |
| `ON CONFLICT DO UPDATE` | โœ“ | โœ— |
| `MERGE` | โœ“ | โœ“ |

### Workaround: Use MERGE

Instead of `INSERT ... ON CONFLICT DO UPDATE`:

```sql
MERGE INTO urls t
USING (VALUES (1000004, 'https://example.com')) AS s(id, url)
ON t.url = s.url
WHEN MATCHED THEN UPDATE SET id = s.id
WHEN NOT MATCHED THEN INSERT (id, url) VALUES (s.id, s.url);
```

---

## Quick Reference

### Diagnostic Queries

**Check index sizes:**
```sql
\di+ table_*
```

**Compare index to table size:**
```sql
SELECT 
    relname AS name,
    pg_size_pretty(pg_relation_size(oid)) AS size
FROM pg_class 
WHERE relname LIKE 'your_table%'
ORDER BY pg_relation_size(oid) DESC;
```

**Check constraint_exclusion setting:**
```sql
SHOW constraint_exclusion;
```

### Decision Tree

```
Is the query scanning impossibly?
โ”œโ”€โ”€ Yes โ†’ Enable constraint_exclusion
โ””โ”€โ”€ No
    โ†“
Is index nearly as large as table?
โ”œโ”€โ”€ Yes, timestamp column โ†’ Function-based index on date
โ”œโ”€โ”€ Yes, large text column โ†’ Hash exclusion constraint
โ””โ”€โ”€ No โ†’ Standard B-Tree is fine
```

---

## Commands

| Command | Action |
|---------|--------|
| `ANALYZE [table]` | Analyze query performance |
| `CHECK-CONSTRAINTS` | Evaluate constraint exclusion opportunity |
| `LOWER-CARDINALITY` | Find function-based index opportunities |
| `HASH-UNIQUE` | Evaluate hash index for large values |
| `COMPARE-INDEXES` | Compare index sizes and performance |

---

## Integration

| Direction | Skill | Relationship |
|-----------|-------|--------------|
| โ† | [debugging](../debugging/) | Query debugging leads here |
| โ†’ | [plan-then-execute](../plan-then-execute/) | Systematic optimization |

Attribution

SimHackerSimHacker
View sourceSee grades on GitHubMore from SimHacker โ†’
SSkills DirectorySkills Directory

Ship a skill? Prove it's safe.

Free 120-pattern security scan, letter grade, and an embeddable README badge.

Submit a skill

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments (0)

No comments yet. Be the first to comment!

SSkills DirectorySkills Directory

Ship a skill? Prove it's safe.

Free 120-pattern security scan, letter grade, and an embeddable README badge.

Submit a skill

Related Skills

Mysql Best Practices

MySQL development best practices for schema design, query optimization, and database administration

2481 votes

Jpa Patterns

Spring Bootไธญ็š„JPA/Hibernateๅฎžไฝ“่ฎพ่ฎกใ€ๅ…ณ็ณปใ€ๆŸฅ่ฏขไผ˜ๅŒ–ใ€ไบ‹ๅŠกใ€ๅฎก่ฎกใ€็ดขๅผ•ใ€ๅˆ†้กตๅ’Œ่ฟžๆŽฅๆฑ ๆจกๅผใ€‚

2456590 votes

Clickhouse Io

ClickHouseๆ•ฐๆฎๅบ“ๆจกๅผใ€ๆŸฅ่ฏขไผ˜ๅŒ–ใ€ๅˆ†ๆžๅ’Œๆ•ฐๆฎๅทฅ็จ‹ๆœ€ไฝณๅฎž่ทต๏ผŒ้€‚็”จไบŽ้ซ˜ๆ€ง่ƒฝๅˆ†ๆžๅทฅไฝœ่ดŸ่ฝฝใ€‚

2456590 votes

Postgres Patterns

ๅŸบไบŽSupabaseๆœ€ไฝณๅฎž่ทต็š„PostgreSQLๆ•ฐๆฎๅบ“ๆจกๅผ๏ผŒ็”จไบŽๆŸฅ่ฏขไผ˜ๅŒ–ใ€ๆžถๆž„่ฎพ่ฎกใ€็ดขๅผ•ๅ’Œๅฎ‰ๅ…จใ€‚

2456590 votes

Sql Pro

Master modern SQL with cloud-native databases, OLTP/OLAP

458250 votes
View all in databases โ†’