[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"header-categories":3,"post-postgresql-indexing-strategies":73,"parsed-post-80d96c15-f730-46db-98dc-9c0902e521c6":147},{"success":4,"data":5},true,{"items":6,"pagination":70},[7,16,24,32,40,48,56,63],{"id":8,"name":9,"description":10,"parentId":11,"createdAt":12,"updatedAt":12,"parent":11,"children":13,"_count":14},"ai-future","AI & The Future","Artificial intelligence and emerging technology",null,"2026-07-24T06:02:45.990Z",[],{"posts":15},1,{"id":17,"name":18,"description":19,"parentId":11,"createdAt":20,"updatedAt":20,"parent":11,"children":21,"_count":22},"tools-productivity","Tools & Productivity","Developer tools and workflow optimization","2026-07-24T06:02:45.712Z",[],{"posts":23},7,{"id":25,"name":26,"description":27,"parentId":11,"createdAt":28,"updatedAt":28,"parent":11,"children":29,"_count":30},"career","Career & Growth","Professional development for developers","2026-07-24T06:02:45.486Z",[],{"posts":31},3,{"id":33,"name":34,"description":35,"parentId":11,"createdAt":36,"updatedAt":36,"parent":11,"children":37,"_count":38},"opinion","Opinion & Analysis","Industry analysis and technical opinions","2026-07-24T06:02:45.272Z",[],{"posts":39},6,{"id":41,"name":42,"description":43,"parentId":11,"createdAt":44,"updatedAt":44,"parent":11,"children":45,"_count":46},"tutorials","Tutorials","Step-by-step learning guides","2026-07-24T06:02:44.965Z",[],{"posts":47},21,{"id":49,"name":50,"description":51,"parentId":11,"createdAt":52,"updatedAt":52,"parent":11,"children":53,"_count":54},"software-engineering","Software Engineering","Best practices, patterns, and principles","2026-07-24T06:02:44.689Z",[],{"posts":55},24,{"id":57,"name":58,"description":59,"parentId":11,"createdAt":60,"updatedAt":60,"parent":11,"children":61,"_count":62},"devops-cloud","DevOps & Cloud","Infrastructure, deployment, and cloud computing","2026-07-24T06:02:44.453Z",[],{"posts":39},{"id":64,"name":65,"description":66,"parentId":11,"createdAt":67,"updatedAt":67,"parent":11,"children":68,"_count":69},"web-development","Web Development","Frontend and backend web development tutorials and guides","2026-07-24T06:02:44.169Z",[],{"posts":55},{"page":15,"limit":71,"total":71,"totalPages":15,"hasNext":72,"hasPrev":72},8,false,{"success":4,"data":74},{"id":75,"slug":76,"title":77,"excerpt":78,"content":79,"status":80,"visibility":81,"featuredImage":82,"canonicalUrl":11,"readingTime":83,"viewCount":84,"commentEnabled":4,"publishedAt":85,"scheduledAt":11,"createdAt":86,"updatedAt":87,"seoTitle":88,"seoDescription":78,"seoKeywords":11,"authorId":89,"author":90,"coAuthors":95,"tags":96,"categories":112,"comments":115,"_count":116,"relatedPosts":118},"80d96c15-f730-46db-98dc-9c0902e521c6","postgresql-indexing-strategies","PostgreSQL Performance: Indexing Strategies That Actually Work","Move beyond basic B-tree indexes. Learn when to use partial indexes, covering indexes, and GIN indexes for real performance gains.","## Indexes Are Not Free\n\nEvery index speeds up reads but slows down writes. The goal isn't \"index everything\" — it's indexing strategically based on your query patterns.\n\n## Analyzing Your Queries\n\n```sql\n-- Always start with EXPLAIN ANALYZE\nEXPLAIN ANALYZE\nSELECT * FROM posts\nWHERE status = 'published' AND published_at > NOW() - INTERVAL '30 days'\nORDER BY published_at DESC\nLIMIT 20;\n```\n\nLook for `Seq Scan` — that's a full table scan you probably want to eliminate.\n\n## Index Types and When to Use Them\n\n### B-Tree (Default)\n\nPerfect for equality and range queries:\n\n```sql\nCREATE INDEX idx_posts_published_at ON posts (published_at DESC);\nCREATE INDEX idx_posts_status ON posts (status);\n```\n\n### Composite Indexes\n\nOrder matters — put the most selective column first:\n\n```sql\n-- Matches: WHERE status = 'published' AND published_at > ...\n-- Also matches: WHERE status = 'published'\n-- Does NOT efficiently match: WHERE published_at > ...\nCREATE INDEX idx_posts_status_date ON posts (status, published_at DESC);\n```\n\n### Partial Indexes\n\nIndex only the rows you actually query:\n\n```sql\n-- Only index published posts (maybe 30% of all posts)\nCREATE INDEX idx_published_posts ON posts (published_at DESC)\nWHERE status = 'published';\n```\n\n::callout{icon=\"i-lucide-zap\" color=\"success\"}\nPartial indexes are smaller, faster to scan, and faster to maintain. Use them when your queries always filter on a specific condition.\n::\n\n### GIN Indexes for Full-Text Search\n\n```sql\n-- Add a tsvector column\nALTER TABLE posts ADD COLUMN search_vector tsvector;\n\n-- Create a GIN index\nCREATE INDEX idx_posts_search ON posts USING GIN (search_vector);\n\n-- Update it with a trigger\nCREATE FUNCTION update_search_vector() RETURNS trigger AS $$\nBEGIN\n  NEW.search_vector := to_tsvector('english', NEW.title || ' ' || NEW.content);\n  RETURN NEW;\nEND;\n$$ LANGUAGE plpgsql;\n```\n\n## With Prisma\n\n```prisma\nmodel Post {\n  id          String   @id @default(uuid())\n  status      String\n  publishedAt DateTime?\n\n  @@index([status, publishedAt(sort: Desc)])\n}\n```\n\n## Common Mistakes\n\n1. **Too many single-column indexes** — Use composites instead\n2. **Indexing low-cardinality columns alone** — A boolean column index rarely helps\n3. **Forgetting INCLUDE columns** — Covering indexes avoid table lookups\n4. **Never running ANALYZE** — Statistics must be fresh for the planner\n\nMonitor with `pg_stat_user_indexes` to find unused indexes consuming write overhead.\n","published","public","https:\u002F\u002Fimages.unsplash.com\u002Fphoto-1461749280684-dccba630e2f6?w=1200&q=80",10,2115,"2026-07-13T06:02:59.241Z","2026-07-24T06:02:59.245Z","2026-07-28T17:13:33.304Z","PostgreSQL Performance: Indexing Strategies That Actually Work | BitBlog","fddb5d93-7a2c-4d86-a06a-fa32e73a01c6",{"email":91,"bio":92,"id":89,"name":93,"avatarUrl":94},"mbeahessilfieprince@gmail.com","Fullstack Software Developer ","Mbeah Essilfie","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F93322394?v=4",[],[97,102,107],{"id":98,"name":99,"color":100,"description":101},"prisma","Prisma","#2d3748","Next-generation Node.js ORM",{"id":103,"name":104,"color":105,"description":106},"performance","Performance","#e535ab","Web performance optimization",{"id":108,"name":109,"color":110,"description":111},"database","Database","#336791","Database design and management",[113,114],{"id":64,"name":65,"description":66},{"id":49,"name":50,"description":51},[],{"comments":117},0,[119,128,137],{"id":120,"slug":121,"title":122,"excerpt":123,"featuredImage":124,"viewCount":125,"readingTime":71,"publishedAt":126,"author":127},"2997028f-4d22-4eb7-9d86-894a54cb559a","building-type-safe-apis-nuxt3-prisma","Building Type-Safe APIs with Nuxt 3 and Prisma","Learn how to build end-to-end type-safe APIs using Nuxt 3 server routes and Prisma ORM for a seamless developer experience.","https:\u002F\u002Fimages.unsplash.com\u002Fphoto-1498050108023-c5249f4df085?w=1200&q=80",1922,"2026-07-23T06:02:46.910Z",{"id":89,"name":93,"avatarUrl":94},{"id":129,"slug":130,"title":131,"excerpt":132,"featuredImage":133,"viewCount":134,"readingTime":83,"publishedAt":135,"author":136},"da9e4553-8b0d-411e-b4ec-f9684017e163","mastering-tailwind-css-design-systems","Mastering Tailwind CSS: From Utility Classes to Design Systems","Go beyond basic utility classes and learn how to build cohesive, maintainable design systems with Tailwind CSS.","https:\u002F\u002Fimages.unsplash.com\u002Fphoto-1555066931-4365d14bab8c?w=1200&q=80",257,"2026-07-21T06:02:49.268Z",{"id":89,"name":93,"avatarUrl":94},{"id":138,"slug":139,"title":140,"excerpt":141,"featuredImage":142,"viewCount":143,"readingTime":144,"publishedAt":145,"author":146},"50add5fc-4026-4267-b917-7f71ea9e35b0","complete-guide-vue3-composables","The Complete Guide to Vue 3 Composables","Understand the power of Vue 3's Composition API through practical, real-world composable patterns that you can use today.","https:\u002F\u002Fimages.unsplash.com\u002Fphoto-1517694712202-14dd9538aa97?w=1200&q=80",990,12,"2026-07-19T06:02:51.753Z",{"id":89,"name":93,"avatarUrl":94},{"data":148,"body":150,"toc":374},{"title":149,"description":149},"",{"type":151,"children":152},"root",[153,162,168,174,187,200,206,213,218,226,232,237,245,251,256,264,275,281,289,295,304,310,356,369],{"type":154,"tag":155,"props":156,"children":158},"element","h2",{"id":157},"indexes-are-not-free",[159],{"type":160,"value":161},"text","Indexes Are Not Free",{"type":154,"tag":163,"props":164,"children":165},"p",{},[166],{"type":160,"value":167},"Every index speeds up reads but slows down writes. The goal isn't \"index everything\" — it's indexing strategically based on your query patterns.",{"type":154,"tag":155,"props":169,"children":171},{"id":170},"analyzing-your-queries",[172],{"type":160,"value":173},"Analyzing Your Queries",{"type":154,"tag":175,"props":176,"children":181},"pre",{"className":177,"code":178,"language":179,"meta":149,"style":180},"language-sql","-- Always start with EXPLAIN ANALYZE\nEXPLAIN ANALYZE\nSELECT * FROM posts\nWHERE status = 'published' AND published_at > NOW() - INTERVAL '30 days'\nORDER BY published_at DESC\nLIMIT 20;\n","sql","undefined",[182],{"type":154,"tag":183,"props":184,"children":185},"code",{"__ignoreMap":149},[186],{"type":160,"value":178},{"type":154,"tag":163,"props":188,"children":189},{},[190,192,198],{"type":160,"value":191},"Look for ",{"type":154,"tag":183,"props":193,"children":195},{"className":194},[],[196],{"type":160,"value":197},"Seq Scan",{"type":160,"value":199}," — that's a full table scan you probably want to eliminate.",{"type":154,"tag":155,"props":201,"children":203},{"id":202},"index-types-and-when-to-use-them",[204],{"type":160,"value":205},"Index Types and When to Use Them",{"type":154,"tag":207,"props":208,"children":210},"h3",{"id":209},"b-tree-default",[211],{"type":160,"value":212},"B-Tree (Default)",{"type":154,"tag":163,"props":214,"children":215},{},[216],{"type":160,"value":217},"Perfect for equality and range queries:",{"type":154,"tag":175,"props":219,"children":221},{"className":177,"code":220,"language":179,"meta":149,"style":180},"CREATE INDEX idx_posts_published_at ON posts (published_at DESC);\nCREATE INDEX idx_posts_status ON posts (status);\n",[222],{"type":154,"tag":183,"props":223,"children":224},{"__ignoreMap":149},[225],{"type":160,"value":220},{"type":154,"tag":207,"props":227,"children":229},{"id":228},"composite-indexes",[230],{"type":160,"value":231},"Composite Indexes",{"type":154,"tag":163,"props":233,"children":234},{},[235],{"type":160,"value":236},"Order matters — put the most selective column first:",{"type":154,"tag":175,"props":238,"children":240},{"className":177,"code":239,"language":179,"meta":149,"style":180},"-- Matches: WHERE status = 'published' AND published_at > ...\n-- Also matches: WHERE status = 'published'\n-- Does NOT efficiently match: WHERE published_at > ...\nCREATE INDEX idx_posts_status_date ON posts (status, published_at DESC);\n",[241],{"type":154,"tag":183,"props":242,"children":243},{"__ignoreMap":149},[244],{"type":160,"value":239},{"type":154,"tag":207,"props":246,"children":248},{"id":247},"partial-indexes",[249],{"type":160,"value":250},"Partial Indexes",{"type":154,"tag":163,"props":252,"children":253},{},[254],{"type":160,"value":255},"Index only the rows you actually query:",{"type":154,"tag":175,"props":257,"children":259},{"className":177,"code":258,"language":179,"meta":149,"style":180},"-- Only index published posts (maybe 30% of all posts)\nCREATE INDEX idx_published_posts ON posts (published_at DESC)\nWHERE status = 'published';\n",[260],{"type":154,"tag":183,"props":261,"children":262},{"__ignoreMap":149},[263],{"type":160,"value":258},{"type":154,"tag":265,"props":266,"children":269},"callout",{"color":267,"icon":268},"success","i-lucide-zap",[270],{"type":154,"tag":163,"props":271,"children":272},{},[273],{"type":160,"value":274},"Partial indexes are smaller, faster to scan, and faster to maintain. Use them when your queries always filter on a specific condition.",{"type":154,"tag":207,"props":276,"children":278},{"id":277},"gin-indexes-for-full-text-search",[279],{"type":160,"value":280},"GIN Indexes for Full-Text Search",{"type":154,"tag":175,"props":282,"children":284},{"className":177,"code":283,"language":179,"meta":149,"style":180},"-- Add a tsvector column\nALTER TABLE posts ADD COLUMN search_vector tsvector;\n\n-- Create a GIN index\nCREATE INDEX idx_posts_search ON posts USING GIN (search_vector);\n\n-- Update it with a trigger\nCREATE FUNCTION update_search_vector() RETURNS trigger AS $$\nBEGIN\n  NEW.search_vector := to_tsvector('english', NEW.title || ' ' || NEW.content);\n  RETURN NEW;\nEND;\n$$ LANGUAGE plpgsql;\n",[285],{"type":154,"tag":183,"props":286,"children":287},{"__ignoreMap":149},[288],{"type":160,"value":283},{"type":154,"tag":155,"props":290,"children":292},{"id":291},"with-prisma",[293],{"type":160,"value":294},"With Prisma",{"type":154,"tag":175,"props":296,"children":299},{"className":297,"code":298,"language":98,"meta":149,"style":180},"language-prisma","model Post {\n  id          String   @id @default(uuid())\n  status      String\n  publishedAt DateTime?\n\n  @@index([status, publishedAt(sort: Desc)])\n}\n",[300],{"type":154,"tag":183,"props":301,"children":302},{"__ignoreMap":149},[303],{"type":160,"value":298},{"type":154,"tag":155,"props":305,"children":307},{"id":306},"common-mistakes",[308],{"type":160,"value":309},"Common Mistakes",{"type":154,"tag":311,"props":312,"children":313},"ol",{},[314,326,336,346],{"type":154,"tag":315,"props":316,"children":317},"li",{},[318,324],{"type":154,"tag":319,"props":320,"children":321},"strong",{},[322],{"type":160,"value":323},"Too many single-column indexes",{"type":160,"value":325}," — Use composites instead",{"type":154,"tag":315,"props":327,"children":328},{},[329,334],{"type":154,"tag":319,"props":330,"children":331},{},[332],{"type":160,"value":333},"Indexing low-cardinality columns alone",{"type":160,"value":335}," — A boolean column index rarely helps",{"type":154,"tag":315,"props":337,"children":338},{},[339,344],{"type":154,"tag":319,"props":340,"children":341},{},[342],{"type":160,"value":343},"Forgetting INCLUDE columns",{"type":160,"value":345}," — Covering indexes avoid table lookups",{"type":154,"tag":315,"props":347,"children":348},{},[349,354],{"type":154,"tag":319,"props":350,"children":351},{},[352],{"type":160,"value":353},"Never running ANALYZE",{"type":160,"value":355}," — Statistics must be fresh for the planner",{"type":154,"tag":163,"props":357,"children":358},{},[359,361,367],{"type":160,"value":360},"Monitor with ",{"type":154,"tag":183,"props":362,"children":364},{"className":363},[],[365],{"type":160,"value":366},"pg_stat_user_indexes",{"type":160,"value":368}," to find unused indexes consuming write overhead.",{"type":154,"tag":370,"props":371,"children":372},"style",{},[373],{"type":160,"value":149},{"title":149,"searchDepth":375,"depth":375,"links":376},2,[377,378,379,385,386],{"id":157,"depth":375,"text":161},{"id":170,"depth":375,"text":173},{"id":202,"depth":375,"text":205,"children":380},[381,382,383,384],{"id":209,"depth":31,"text":212},{"id":228,"depth":31,"text":231},{"id":247,"depth":31,"text":250},{"id":277,"depth":31,"text":280},{"id":291,"depth":375,"text":294},{"id":306,"depth":375,"text":309}]