Skip to content

chore: add json vs jsonb demo scripts #7266

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions internal_docs/vignettes/json-jsonb-demo/.eslintrc.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
module.exports = {
env: {
node: true,
es2022: true
},
extends: ['eslint:recommended', 'plugin:@typescript-eslint/recommended'],
parser: '@typescript-eslint/parser',
parserOptions: {
ecmaVersion: 'latest',
sourceType: 'module'
},
plugins: ['@typescript-eslint'],
rules: {
indent: ['error', 2],
'linebreak-style': ['error', 'unix'],
quotes: ['error', 'single'],
semi: ['error', 'always'],
'comma-dangle': ['error', 'never']
}
};
37 changes: 37 additions & 0 deletions internal_docs/vignettes/json-jsonb-demo/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# Node.js dependencies
node_modules/
package-lock.json
yarn.lock

# PGlite data files
data/
*.db
*.sqlite
postgres_socket/

# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# Runtime data
pids
*.pid
*.seed
*.pid.lock

# Environment variables
.env
.env.local
.env.development.local
.env.test.local
.env.production.local

# Editor directories and files
.idea/
.vscode/
*.swp
*.swo
*~
3 changes: 3 additions & 0 deletions internal_docs/vignettes/json-jsonb-demo/.prettierrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"trailingComma": "es5"
}
147 changes: 147 additions & 0 deletions internal_docs/vignettes/json-jsonb-demo/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
# PostgreSQL JSON vs JSONB Demo

This project demonstrates the key differences between PostgreSQL's JSON and JSONB data types. The most striking difference is how they handle key ordering:

```
Original input: { "z": 26, "a": 1, "m": 13 }

JSON output: { "z": 26, "a": 1, "m": 13 } | JSONB output: { "a": 1, "m": 13, "z": 26 }
(preserves original order) | (sorts keys alphabetically)
```

Here's a real example from our test data:

```
Original input order: ['QVZZCJFR', 'DAUFW', 'DXRMYF', 'SEETRJBUU', ...]

JSON output: { | JSONB output: {
"QVZZCJFR": 8, | "B": 1,
"DAUFW": 5, | "XT": 2,
"DXRMYF": 6, | "RHD": 3,
"SEETRJBUU": 9, | "YPSE": 4,
"YPSE": 4, | "DAUFW": 5,
"DEGAZFI": 7, | "DXRMYF": 6,
"XT": 2, | "DEGAZFI": 7,
"RHD": 3, | "QVZZCJFR": 8,
"B": 1, | "SEETRJBUU": 9,
"JCXSRJOEXE": 10 | "JCXSRJOEXE": 10
} | }
```

JSON preserves your exact input format, while JSONB optimizes for querying by reordering keys lexicographically. This project provides practical examples and performance comparisons to help developers understand when to use each type.

## Features

- **Key Order Comparison**: Demonstrates how JSON preserves key order while JSONB sorts keys lexicographically
- **Performance Benchmarks**: Compares insert and query performance between JSON and JSONB
- **Query Capabilities**: Shows various query operations and operators available for both types
- **Index Impact**: Demonstrates the effect of GIN indexing on JSONB queries
- **TypeScript Support**: Fully typed codebase with proper type definitions

## Prerequisites

- Node.js (v18 or higher)
- pnpm (v10.2.0 or higher)
- PostgreSQL (v12 or higher) - Optional, as the demo can use PGlite by default

## Installation

1. Clone the repository
2. Install dependencies:
```bash
pnpm install
```

## Configuration

The project can use either PGlite (in-memory PostgreSQL) or a real PostgreSQL database. Configure this in `src/config/db-config.ts`:

```typescript
// Set to true to use PGlite, false to use PostgreSQL
export const USE_PGLITE: boolean = true;
```

If using PostgreSQL, set the following environment variables or update the defaults in `src/services/db-service.ts`:
- `DB_USER` (default: "postgres")
- `DB_HOST` (default: "localhost")
- `DB_NAME` (default: "json_demo")
- `DB_PASSWORD` (default: "postgres")
- `DB_PORT` (default: "5432")

## Usage

Run the following commands to see different aspects of JSON vs JSONB:

```bash
# Run the main demo (key order comparison)
pnpm start

# Run performance benchmarks
pnpm run performance

# Run query examples
pnpm run query

# Run key order comparison
pnpm run compare
```

## Demo Scripts

1. **compare.ts**: Demonstrates key order preservation differences
- Shows how JSON preserves input key order
- Shows how JSONB reorders keys lexicographically
- Compares storage sizes

2. **performance.ts**: Benchmarks performance characteristics
- Insert performance comparison
- Query performance comparison
- Index impact on queries
- JSONB-specific operator performance

3. **query-examples.ts**: Shows query capabilities
- Basic key access
- Nested key access
- Array access
- Filtering
- JSONB-specific operators

## Key Findings

### When to use JSON
- When you need to preserve exact document format including whitespace and key order
- For write-heavy operations with minimal querying
- When input validation is more important than query performance

### When to use JSONB
- When you need frequent querying of the JSON data
- When you need indexing capabilities
- When query performance is critical
- When storage space is a concern
- When key order preservation is not required

## Development

- `pnpm run format`: Format code using Prettier
- `pnpm run lint`: Run ESLint
- `pnpm run typecheck`: Run TypeScript type checking

## Project Structure

```
src/
├── config/
│ └── db-config.ts # Database configuration
├── services/
│ └── db-service.ts # Database service with PG/PGlite support
├── types/
│ └── db.types.ts # TypeScript type definitions
├── compare.ts # Key order comparison demo
├── performance.ts # Performance benchmarks
├── query-examples.ts # Query capabilities demo
└── index.ts # Main entry point
```

## License

MIT
45 changes: 45 additions & 0 deletions internal_docs/vignettes/json-jsonb-demo/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
{
"name": "pglite-json-jsonb-demo",
"version": "1.0.0",
"description": "Demonstration of PostgreSQL JSON vs JSONB storage behavior using PGlite or PostgreSQL",
"main": "src/index.ts",
"type": "module",
"scripts": {
"start": "node --import 'data:text/javascript,import { register } from \"node:module\"; import { pathToFileURL } from \"node:url\"; register(\"ts-node/esm\", pathToFileURL(\"./\"));' --no-warnings src/index.ts",
"compare": "node --import 'data:text/javascript,import { register } from \"node:module\"; import { pathToFileURL } from \"node:url\"; register(\"ts-node/esm\", pathToFileURL(\"./\"));' --no-warnings src/compare.ts",
"performance": "node --import 'data:text/javascript,import { register } from \"node:module\"; import { pathToFileURL } from \"node:url\"; register(\"ts-node/esm\", pathToFileURL(\"./\"));' --no-warnings src/performance.ts",
"query": "node --import 'data:text/javascript,import { register } from \"node:module\"; import { pathToFileURL } from \"node:url\"; register(\"ts-node/esm\", pathToFileURL(\"./\"));' --no-warnings src/query-examples.ts",
"format": "prettier --write \"src/**/*.ts\"",
"lint": "eslint \"src/**/*.ts\"",
"typecheck": "tsc --noEmit",
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [
"postgresql",
"json",
"jsonb",
"pglite",
"database"
],
"author": "",
"license": "MIT",
"dependencies": {
"@electric-sql/pglite": "latest"
},
"devDependencies": {
"@types/node": "^22.5.4",
"@types/pg": "^8.11.14",
"@typescript-eslint/eslint-plugin": "^7.16.1",
"@typescript-eslint/parser": "^7.16.1",
"eslint": "^8.57.0",
"eslint-plugin-import": "^2.29.1",
"pg": "^8.11.3",
"prettier": "^3.1.0",
"ts-node": "^10.9.2",
"typescript": "~5.4.5"
},
"packageManager": "[email protected]",
"optionalDependencies": {
"pg": "^8.11.3"
}
}
Loading