Skip to content

Blog refresh: Indexes series part 3, Hash Indexes (Prisma 7, re-verified measurements)#8040

Open
vanrensbird wants to merge 1 commit into
mainfrom
blog/refresh-indexes-part-3
Open

Blog refresh: Indexes series part 3, Hash Indexes (Prisma 7, re-verified measurements)#8040
vanrensbird wants to merge 1 commit into
mainfrom
blog/refresh-indexes-part-3

Conversation

@vanrensbird

@vanrensbird vanrensbird commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

What

Refreshes improving-query-performance-using-indexes-3-kduk351qv1 (Oct 2022) for Prisma ORM 7, completing the three-part indexes series (part 2 in #8029, part 1 in #8039). Reviewed and approved by Martin on localhost.

Verification

Every command and number was re-run today on prisma@7.8 + PostgreSQL 17: the part-2 project rebuilt from scratch (500,000 seeded users on a local Prisma Postgres instance via prisma dev), the unindexed equality query measured at a 64.1ms sequential scan, @@index([lastName], type: Hash) applied via db push (DDL confirmed from pg_indexes), and the same query re-measured at 1.567ms via a bitmap scan on the hash index, roughly 41x. All output blocks in the post are verbatim from this run.

Changes

  • Modernized walkthrough: prisma-client generator, driver adapter, local Prisma Postgres, client-extension timing (replaces the removed $use middleware), continuing directly from part 2's project
  • Answer-first lead with measured numbers + Updated (July 2026) callout + updatedAt
  • FAQ as <Accordions> (how to add a hash index in Prisma, hash vs B-tree, measured speedup)
  • Inline "Overview" TOC removed (layout renders InlineTOC)
  • Link conventions: Wikipedia links and a third-party Big O tutorial link removed (inline gloss instead); Prisma Postgres → docs; Postgres hash README kept (canonical)
  • Fixed the muddled hash key/code definitions to match how Postgres derives bucket numbers

Follow-ups tracked separately: part 2 still carries an inline TOC and no Updated callout (two-line sweep), and a finished satisfies-operator refresh awaits its own PR.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Documentation
    • Refreshed the blog post to focus on hash-index performance tuning with updated guidance and examples.
    • Added a new revision note and streamlined the walkthrough to emphasize measuring query speed before and after the index change.
    • Updated benchmark results, query plans, and closing notes to match the latest Prisma ORM and PostgreSQL verification flow.

…ndexes

Completes the series refresh (#8029 part 2, #8039 part 1). Rebuilt for
Prisma ORM 7.8: prisma-client generator, driver adapter, local Prisma
Postgres via prisma dev, measurements re-run end-to-end today (seq scan
64.1ms -> hash index 1.567ms over 500k rows, ~41x, PostgreSQL 17).
content-seo-geo pass: answer-first lead, Updated callout, FAQ accordions,
no inline TOC, canonical links only. Reviewed by Martin.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@vanrensbird vanrensbird requested a review from ankur-arch July 8, 2026 15:33
@vercel

vercel Bot commented Jul 8, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
blog Ready Ready Preview, Comment Jul 8, 2026 3:36pm
docs Ready Ready Preview, Comment Jul 8, 2026 3:36pm
eclipse Ready Ready Preview, Comment Jul 8, 2026 3:36pm
site Ready Ready Preview, Comment Jul 8, 2026 3:36pm

Request Review

@coderabbitai

coderabbitai Bot commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Walkthrough

The MDX blog article on query performance was revised to center on hash indexes rather than the prior content. Front matter metadata, introductory explanations, and the Prisma walkthrough were rewritten to include a Prisma ORM 7 measurement script, updated schema, benchmark outputs, and revised FAQ/summary sections.

Changes

Hash Index Blog Post Rewrite

Layer / File(s) Summary
Front matter metadata update
apps/blog/content/blog/improving-query-performance-using-indexes-3-kduk351qv1/index.mdx
Updated updatedAt date and rewrote metaTitle/metaDescription to reflect hash-index performance focus.
Introduction and conceptual rewrite
apps/blog/content/blog/improving-query-performance-using-indexes-3-kduk351qv1/index.mdx
Rewrote the intro, hash table explanation, and "when to use" section; added a July 2026 revision callout and new setup lead-in continuing from part two with a Prisma ORM 7 measurement approach.
Measurement workflow and benchmark content
apps/blog/content/blog/improving-query-performance-using-indexes-3-kduk351qv1/index.mdx
Replaced the prior REST/migration workflow with a measurement-driven sequence: updated schema with a hash index, added a slow-query measurement section, an index-addition step via npx prisma db push, refreshed benchmark/EXPLAIN ANALYZE output, and updated FAQ and summary sections.

Estimated code review effort: 2 (Simple) | ~10 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly reflects the main change: a refreshed Part 3 blog post about hash indexes with Prisma 7 and re-verified measurements.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (2)
apps/blog/content/blog/improving-query-performance-using-indexes-3-kduk351qv1/index.mdx (2)

101-103: 🔒 Security & Privacy | 🔵 Trivial | ⚡ Quick win

Consider showing a parameterized query instead of $queryRawUnsafe with string interpolation.

The excerpt escapes single quotes with name.replace(/'/g, "''"), but $queryRawUnsafe with interpolated values is a pattern readers may copy without the escaping. A brief note or use of $queryRaw with a tagged template would model safer practices.

🛡️ Safer alternative using tagged template
-const plan = await prisma.$queryRawUnsafe<{ 'QUERY PLAN': string }[]>(
-  `EXPLAIN ANALYZE SELECT * FROM "User" WHERE "lastName" = '${name.replace(/'/g, "''")}'`
-)
+const plan = await prisma.$queryRaw<{ 'QUERY PLAN': string }[]>(
+  `EXPLAIN ANALYZE SELECT * FROM "User" WHERE "lastName" = $1`, name
+)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@apps/blog/content/blog/improving-query-performance-using-indexes-3-kduk351qv1/index.mdx`
around lines 101 - 103, The example in the query plan snippet uses
$queryRawUnsafe with string interpolation, which can encourage unsafe copy-paste
patterns. Update the example in the blog content to use Prisma’s parameterized
$queryRaw tagged template (or add a brief note explaining the escaping) so the
query is shown as a safer pattern; use the prisma.$queryRawUnsafe call and the
EXPLAIN ANALYZE example as the places to adjust.

31-31: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Consider rewording to avoid three consecutive sentences starting with "Hash".

Lines 31 begins three successive sentences with the word "Hash" ("Hash indexes use…", "Hash tables (also known…", "Hash function: a function…"). A small reword would improve readability.

✏️ Suggested rewording
-Hash indexes use the hash table data structure. Hash tables (also known as hash maps) allow fast data retrieval in almost _constant_ time (`O(1)`), meaning the retrieval time of a record won't be affected by the size of the data being searched. (Big O notation describes how an algorithm's cost grows with input size; `O(1)` means the cost stays flat.)
+Hash indexes use the hash table data structure. Also known as hash maps, these allow fast data retrieval in almost _constant_ time (`O(1)`), meaning the retrieval time of a record won't be affected by the size of the data being searched. (Big O notation describes how an algorithm's cost grows with input size; `O(1)` means the cost stays flat.)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@apps/blog/content/blog/improving-query-performance-using-indexes-3-kduk351qv1/index.mdx`
at line 31, Reword the opening sentences in the blog post section around the
hash index explanation to avoid repeating “Hash” at the start of three
consecutive sentences. Update the phrasing in the relevant paragraph in the blog
content so the discussion still explains hash indexes, hash tables, and the hash
function clearly, but with varied sentence openings for better readability.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@apps/blog/content/blog/improving-query-performance-using-indexes-3-kduk351qv1/index.mdx`:
- Line 182: The phrasing in the blog text overstates the query plan by saying
Postgres uses the hash index to locate rows “directly,” while the EXPLAIN
ANALYZE output for the surrounding example shows a Bitmap Heap Scan with a
Bitmap Index Scan child. Update the sentence in the markdown content to describe
that the hash index is used to find matching rows via the bitmap scan path, and
keep the performance numbers intact; the fix is in the prose near the
sequential-scan comparison in the blog post.

---

Nitpick comments:
In
`@apps/blog/content/blog/improving-query-performance-using-indexes-3-kduk351qv1/index.mdx`:
- Around line 101-103: The example in the query plan snippet uses
$queryRawUnsafe with string interpolation, which can encourage unsafe copy-paste
patterns. Update the example in the blog content to use Prisma’s parameterized
$queryRaw tagged template (or add a brief note explaining the escaping) so the
query is shown as a safer pattern; use the prisma.$queryRawUnsafe call and the
EXPLAIN ANALYZE example as the places to adjust.
- Line 31: Reword the opening sentences in the blog post section around the hash
index explanation to avoid repeating “Hash” at the start of three consecutive
sentences. Update the phrasing in the relevant paragraph in the blog content so
the discussion still explains hash indexes, hash tables, and the hash function
clearly, but with varied sentence openings for better readability.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: f0ee8de6-e7f6-49e6-9e4c-537827c7e078

📥 Commits

Reviewing files that changed from the base of the PR and between d062d35 and 48bd7c6.

📒 Files selected for processing (1)
  • apps/blog/content/blog/improving-query-performance-using-indexes-3-kduk351qv1/index.mdx

```

![](/improving-query-performance-using-indexes-3-kduk351qv1/imgs/194080275-c4bd1059-595b-40b0-b2d9-b05339dac8cc.png)
The sequential scan is gone. Postgres uses the hash index to locate the matching rows directly, and execution time drops from 64.1ms to 1.6ms, roughly a 41x improvement. At the application level, the `findMany` call returning all 962 matching rows settles around 14 to 19ms instead of 76 to 80ms.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Clarify "directly" wording to match the Bitmap scan shown in EXPLAIN ANALYZE.

The text says "Postgres uses the hash index to locate the matching rows directly," but the EXPLAIN output on lines 173-177 shows a Bitmap Heap Scan with a child Bitmap Index Scan, not a direct/plain Index Scan. While the hash index is indeed being used, saying "directly" may confuse readers who compare the prose to the query plan. Consider "Postgres uses the hash index to find the matching rows" or note the bitmap scan step.

✏️ Suggested wording
-The sequential scan is gone. Postgres uses the hash index to locate the matching rows directly, and execution time drops from 64.1ms to 1.6ms, roughly a 41x improvement.
+The sequential scan is gone. Postgres uses the hash index via a bitmap scan to find the matching rows, and execution time drops from 64.1ms to 1.6ms, roughly a 41x improvement.
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
The sequential scan is gone. Postgres uses the hash index to locate the matching rows directly, and execution time drops from 64.1ms to 1.6ms, roughly a 41x improvement. At the application level, the `findMany` call returning all 962 matching rows settles around 14 to 19ms instead of 76 to 80ms.
The sequential scan is gone. Postgres uses the hash index via a bitmap scan to find the matching rows, and execution time drops from 64.1ms to 1.6ms, roughly a 41x improvement.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@apps/blog/content/blog/improving-query-performance-using-indexes-3-kduk351qv1/index.mdx`
at line 182, The phrasing in the blog text overstates the query plan by saying
Postgres uses the hash index to locate rows “directly,” while the EXPLAIN
ANALYZE output for the surrounding example shows a Bitmap Heap Scan with a
Bitmap Index Scan child. Update the sentence in the markdown content to describe
that the hash index is used to find matching rows via the bitmap scan path, and
keep the performance numbers intact; the fix is in the prose near the
sequential-scan comparison in the blog post.

@argos-ci

argos-ci Bot commented Jul 8, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Argos notifications ↗︎

Build Status Details Updated (UTC)
default (Inspect) ✅ No changes detected - Jul 8, 2026, 3:44 PM

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant