[{"data":1,"prerenderedAt":2799},["ShallowReactive",2],{"navigation_docs":3,"-tu-hoc-database-postgresql-dac-thu-performance":420,"-tu-hoc-database-postgresql-dac-thu-performance-surround":2794},[4,153],{"title":5,"icon":6,"path":7,"stem":8,"children":9,"page":26},"Phỏng vấn .NET","i-lucide-briefcase","\u002Fphong-van","1.phong-van",[10,27,66,111,128],{"title":11,"icon":12,"path":13,"stem":14,"children":15,"page":26},"Tổng quan","i-lucide-compass","\u002Fphong-van\u002Ftong-quan","1.phong-van\u002F1.tong-quan",[16,21],{"title":17,"path":18,"stem":19,"icon":20},"Thị trường HCM","\u002Fphong-van\u002Ftong-quan\u002Fthi-truong","1.phong-van\u002F1.tong-quan\u002F1.thi-truong","i-lucide-trending-up",{"title":22,"path":23,"stem":24,"icon":25},"Lộ trình 7 ngày","\u002Fphong-van\u002Ftong-quan\u002Flo-trinh","1.phong-van\u002F1.tong-quan\u002F2.lo-trinh","i-lucide-calendar-days",false,{"title":22,"icon":25,"path":28,"stem":29,"children":30,"page":26},"\u002Fphong-van\u002Flo-trinh","1.phong-van\u002F2.lo-trinh",[31,36,41,46,51,56,61],{"title":32,"path":33,"stem":34,"icon":35},"Ngày 1 — C# cơ bản","\u002Fphong-van\u002Flo-trinh\u002Fngay-1-csharp-co-ban","1.phong-van\u002F2.lo-trinh\u002F1.ngay-1-csharp-co-ban","i-lucide-1",{"title":37,"path":38,"stem":39,"icon":40},"Ngày 2 — OOP và SOLID","\u002Fphong-van\u002Flo-trinh\u002Fngay-2-oop-solid","1.phong-van\u002F2.lo-trinh\u002F2.ngay-2-oop-solid","i-lucide-2",{"title":42,"path":43,"stem":44,"icon":45},"Ngày 3 — C# nâng cao","\u002Fphong-van\u002Flo-trinh\u002Fngay-3-csharp-nang-cao","1.phong-van\u002F2.lo-trinh\u002F3.ngay-3-csharp-nang-cao","i-lucide-3",{"title":47,"path":48,"stem":49,"icon":50},"Ngày 4 — Database và SQL","\u002Fphong-van\u002Flo-trinh\u002Fngay-4-database-sql","1.phong-van\u002F2.lo-trinh\u002F4.ngay-4-database-sql","i-lucide-4",{"title":52,"path":53,"stem":54,"icon":55},"Ngày 5 — ASP.NET Core và EF Core","\u002Fphong-van\u002Flo-trinh\u002Fngay-5-aspnet-efcore","1.phong-van\u002F2.lo-trinh\u002F5.ngay-5-aspnet-efcore","i-lucide-5",{"title":57,"path":58,"stem":59,"icon":60},"Ngày 6 — DSA coding","\u002Fphong-van\u002Flo-trinh\u002Fngay-6-dsa","1.phong-van\u002F2.lo-trinh\u002F6.ngay-6-dsa","i-lucide-6",{"title":62,"path":63,"stem":64,"icon":65},"Ngày 7 — Mock và HR","\u002Fphong-van\u002Flo-trinh\u002Fngay-7-mock-interview","1.phong-van\u002F2.lo-trinh\u002F7.ngay-7-mock-interview","i-lucide-7",{"title":67,"icon":68,"path":69,"stem":70,"children":71,"page":26},"Ngân hàng câu hỏi","i-lucide-database","\u002Fphong-van\u002Fngan-hang-cau-hoi","1.phong-van\u002F3.ngan-hang-cau-hoi",[72,77,82,87,92,97,102,107],{"title":73,"path":74,"stem":75,"icon":76},"C# (60+ câu)","\u002Fphong-van\u002Fngan-hang-cau-hoi\u002Fcsharp","1.phong-van\u002F3.ngan-hang-cau-hoi\u002F1.csharp","i-lucide-hash",{"title":78,"path":79,"stem":80,"icon":81},"OOP và SOLID (40+)","\u002Fphong-van\u002Fngan-hang-cau-hoi\u002Foop","1.phong-van\u002F3.ngan-hang-cau-hoi\u002F2.oop","i-lucide-shapes",{"title":83,"path":84,"stem":85,"icon":86},"SQL (40+)","\u002Fphong-van\u002Fngan-hang-cau-hoi\u002Fsql","1.phong-van\u002F3.ngan-hang-cau-hoi\u002F3.sql","i-lucide-database-zap",{"title":88,"path":89,"stem":90,"icon":91},"ASP.NET và EF (50+)","\u002Fphong-van\u002Fngan-hang-cau-hoi\u002Faspnet-ef","1.phong-van\u002F3.ngan-hang-cau-hoi\u002F4.aspnet-ef","i-lucide-server",{"title":93,"path":94,"stem":95,"icon":96},"DSA và Coding (30+)","\u002Fphong-van\u002Fngan-hang-cau-hoi\u002Fdsa-coding","1.phong-van\u002F3.ngan-hang-cau-hoi\u002F5.dsa-coding","i-lucide-binary",{"title":98,"path":99,"stem":100,"icon":101},"HR và Soft skill (25+)","\u002Fphong-van\u002Fngan-hang-cau-hoi\u002Fhr-behavior","1.phong-van\u002F3.ngan-hang-cau-hoi\u002F6.hr-behavior","i-lucide-users",{"title":103,"path":104,"stem":105,"icon":106},"Design Pattern (55+)","\u002Fphong-van\u002Fngan-hang-cau-hoi\u002Fdesign-pattern","1.phong-van\u002F3.ngan-hang-cau-hoi\u002F7.design-pattern","i-lucide-puzzle",{"title":108,"path":109,"stem":110,"icon":91},"ASP.NET MVC và Web API","\u002Fphong-van\u002Fngan-hang-cau-hoi\u002Faspnet-mvc-webapi","1.phong-van\u002F3.ngan-hang-cau-hoi\u002F8.aspnet-mvc-webapi",{"title":112,"itle":113,"icon":114,"path":115,"stem":116,"children":117,"page":26},"Tai Lieu","Tài liệu và Cheat sheet","i-lucide-book-marked","\u002Fphong-van\u002Ftai-lieu","1.phong-van\u002F4.tai-lieu",[118,123],{"title":119,"path":120,"stem":121,"icon":122},"Cheat Sheet","\u002Fphong-van\u002Ftai-lieu\u002Fcheatsheet","1.phong-van\u002F4.tai-lieu\u002F1.cheatsheet","i-lucide-clipboard-list",{"title":124,"path":125,"stem":126,"icon":127},"Nguồn tham khảo","\u002Fphong-van\u002Ftai-lieu\u002Fnguon","1.phong-van\u002F4.tai-lieu\u002F2.nguon","i-lucide-link",{"title":129,"icon":130,"path":131,"stem":132,"children":133,"page":26},"Phỏng vấn English","i-lucide-globe","\u002Fphong-van\u002Fenglish-interview","1.phong-van\u002F5.english-interview",[134,138,143,148],{"title":135,"path":136,"stem":137,"icon":130},"Tổng quan English","\u002Fphong-van\u002Fenglish-interview\u002Ftong-quan","1.phong-van\u002F5.english-interview\u002F1.tong-quan",{"title":139,"path":140,"stem":141,"icon":142},"Vocabulary","\u002Fphong-van\u002Fenglish-interview\u002Fvocabulary","1.phong-van\u002F5.english-interview\u002F2.vocabulary","i-lucide-book-a",{"title":144,"path":145,"stem":146,"icon":147},"Technical Q và A (EN)","\u002Fphong-van\u002Fenglish-interview\u002Ftechnical-en","1.phong-van\u002F5.english-interview\u002F3.technical-en","i-lucide-code",{"title":149,"path":150,"stem":151,"icon":152},"Behavioral (EN)","\u002Fphong-van\u002Fenglish-interview\u002Fbehavioral-en","1.phong-van\u002F5.english-interview\u002F4.behavioral-en","i-lucide-message-square-text",{"title":154,"icon":155,"path":156,"stem":157,"children":158},"Tự học","i-lucide-graduation-cap","\u002Ftu-hoc","2.tu-hoc",[159,161,287,310,333,357,384],{"title":154,"path":156,"stem":160,"icon":155},"2.tu-hoc\u002Findex",{"title":162,"icon":68,"path":163,"stem":164,"children":165},"Database","\u002Ftu-hoc\u002Fdatabase","2.tu-hoc\u002F1.database\u002Findex",[166,167,197,222,243,248],{"title":162,"path":163,"stem":164,"icon":68},{"title":168,"icon":91,"path":169,"stem":170,"children":171,"page":26},"SQL Server","\u002Ftu-hoc\u002Fdatabase\u002Fsql-server","2.tu-hoc\u002F1.database\u002F2.sql-server",[172,177,182,187,192],{"title":173,"path":174,"stem":175,"icon":176},"1. Giới thiệu và Cài đặt","\u002Ftu-hoc\u002Fdatabase\u002Fsql-server\u002Fgioi-thieu-cai-dat","2.tu-hoc\u002F1.database\u002F2.sql-server\u002F1.gioi-thieu-cai-dat","i-lucide-play-circle",{"title":178,"path":179,"stem":180,"icon":181},"2. Cú pháp cơ bản","\u002Ftu-hoc\u002Fdatabase\u002Fsql-server\u002Fcu-phap-co-ban","2.tu-hoc\u002F1.database\u002F2.sql-server\u002F2.cu-phap-co-ban","i-lucide-code-2",{"title":183,"path":184,"stem":185,"icon":186},"3. Truy vấn nâng cao","\u002Ftu-hoc\u002Fdatabase\u002Fsql-server\u002Ftruy-van-nang-cao","2.tu-hoc\u002F1.database\u002F2.sql-server\u002F3.truy-van-nang-cao","i-lucide-git-merge",{"title":188,"path":189,"stem":190,"icon":191},"4. Đặc thù và Performance","\u002Ftu-hoc\u002Fdatabase\u002Fsql-server\u002Fdac-thu-performance","2.tu-hoc\u002F1.database\u002F2.sql-server\u002F4.dac-thu-performance","i-lucide-gauge",{"title":193,"path":194,"stem":195,"icon":196},"5. Q và A phỏng vấn","\u002Ftu-hoc\u002Fdatabase\u002Fsql-server\u002Fcau-hoi-phong-van","2.tu-hoc\u002F1.database\u002F2.sql-server\u002F5.cau-hoi-phong-van","i-lucide-message-circle-question",{"title":198,"icon":199,"path":200,"stem":201,"children":202,"page":26},"PostgreSQL","i-simple-icons-postgresql","\u002Ftu-hoc\u002Fdatabase\u002Fpostgresql","2.tu-hoc\u002F1.database\u002F3.postgresql",[203,206,209,212,215,218],{"title":173,"path":204,"stem":205,"icon":176},"\u002Ftu-hoc\u002Fdatabase\u002Fpostgresql\u002Fgioi-thieu-cai-dat","2.tu-hoc\u002F1.database\u002F3.postgresql\u002F1.gioi-thieu-cai-dat",{"title":178,"path":207,"stem":208,"icon":181},"\u002Ftu-hoc\u002Fdatabase\u002Fpostgresql\u002Fcu-phap-co-ban","2.tu-hoc\u002F1.database\u002F3.postgresql\u002F2.cu-phap-co-ban",{"title":183,"path":210,"stem":211,"icon":186},"\u002Ftu-hoc\u002Fdatabase\u002Fpostgresql\u002Ftruy-van-nang-cao","2.tu-hoc\u002F1.database\u002F3.postgresql\u002F3.truy-van-nang-cao",{"title":188,"path":213,"stem":214,"icon":191},"\u002Ftu-hoc\u002Fdatabase\u002Fpostgresql\u002Fdac-thu-performance","2.tu-hoc\u002F1.database\u002F3.postgresql\u002F4.dac-thu-performance",{"title":193,"path":216,"stem":217,"icon":196},"\u002Ftu-hoc\u002Fdatabase\u002Fpostgresql\u002Fcau-hoi-phong-van","2.tu-hoc\u002F1.database\u002F3.postgresql\u002F5.cau-hoi-phong-van",{"title":219,"path":220,"stem":221,"icon":96},"6. Tích hợp C# và Postgres","\u002Ftu-hoc\u002Fdatabase\u002Fpostgresql\u002Ftich-hop-csharp","2.tu-hoc\u002F1.database\u002F3.postgresql\u002F6.tich-hop-csharp",{"title":223,"icon":224,"path":225,"stem":226,"children":227,"page":26},"MySQL","i-simple-icons-mysql","\u002Ftu-hoc\u002Fdatabase\u002Fmysql","2.tu-hoc\u002F1.database\u002F4.mysql",[228,231,234,237,240],{"title":173,"path":229,"stem":230,"icon":176},"\u002Ftu-hoc\u002Fdatabase\u002Fmysql\u002Fgioi-thieu-cai-dat","2.tu-hoc\u002F1.database\u002F4.mysql\u002F1.gioi-thieu-cai-dat",{"title":178,"path":232,"stem":233,"icon":181},"\u002Ftu-hoc\u002Fdatabase\u002Fmysql\u002Fcu-phap-co-ban","2.tu-hoc\u002F1.database\u002F4.mysql\u002F2.cu-phap-co-ban",{"title":183,"path":235,"stem":236,"icon":186},"\u002Ftu-hoc\u002Fdatabase\u002Fmysql\u002Ftruy-van-nang-cao","2.tu-hoc\u002F1.database\u002F4.mysql\u002F3.truy-van-nang-cao",{"title":188,"path":238,"stem":239,"icon":191},"\u002Ftu-hoc\u002Fdatabase\u002Fmysql\u002Fdac-thu-performance","2.tu-hoc\u002F1.database\u002F4.mysql\u002F4.dac-thu-performance",{"title":193,"path":241,"stem":242,"icon":196},"\u002Ftu-hoc\u002Fdatabase\u002Fmysql\u002Fcau-hoi-phong-van","2.tu-hoc\u002F1.database\u002F4.mysql\u002F5.cau-hoi-phong-van",{"title":244,"path":245,"stem":246,"icon":247},"So sánh 3 RDBMS","\u002Ftu-hoc\u002Fdatabase\u002Fso-sanh","2.tu-hoc\u002F1.database\u002F5.so-sanh","i-lucide-columns-3",{"title":249,"path":250,"stem":251,"children":252,"icon":254},"Supabase (BaaS)","\u002Ftu-hoc\u002Fdatabase\u002Fsupabase","2.tu-hoc\u002F1.database\u002F6.supabase\u002Findex",[253,255,259,264,269,274,278,283],{"title":249,"path":250,"stem":251,"icon":254},"i-simple-icons-supabase",{"title":256,"path":257,"stem":258,"icon":68},"1. Database","\u002Ftu-hoc\u002Fdatabase\u002Fsupabase\u002Fdatabase","2.tu-hoc\u002F1.database\u002F6.supabase\u002F1.database",{"title":260,"path":261,"stem":262,"icon":263},"2. Authentication","\u002Ftu-hoc\u002Fdatabase\u002Fsupabase\u002Fauthentication","2.tu-hoc\u002F1.database\u002F6.supabase\u002F2.authentication","i-lucide-key",{"title":265,"path":266,"stem":267,"icon":268},"3. Storage & Realtime","\u002Ftu-hoc\u002Fdatabase\u002Fsupabase\u002Fstorage-realtime","2.tu-hoc\u002F1.database\u002F6.supabase\u002F3.storage-realtime","i-lucide-zap",{"title":270,"path":271,"stem":272,"icon":273},"4. Edge Functions & AI","\u002Ftu-hoc\u002Fdatabase\u002Fsupabase\u002Ffunctions-ai","2.tu-hoc\u002F1.database\u002F6.supabase\u002F4.functions-ai","i-lucide-brain",{"title":275,"path":276,"stem":277,"icon":181},"5. API & SDKs","\u002Ftu-hoc\u002Fdatabase\u002Fsupabase\u002Fapi-sdk","2.tu-hoc\u002F1.database\u002F6.supabase\u002F5.api-sdk",{"title":279,"path":280,"stem":281,"icon":282},"6. Platform & Deploy","\u002Ftu-hoc\u002Fdatabase\u002Fsupabase\u002Fplatform-deploy","2.tu-hoc\u002F1.database\u002F6.supabase\u002F6.platform-deploy","i-lucide-cloud",{"title":284,"path":285,"stem":286,"icon":196},"7. Interview & Q&A","\u002Ftu-hoc\u002Fdatabase\u002Fsupabase\u002Finterview","2.tu-hoc\u002F1.database\u002F6.supabase\u002F7.interview",{"title":288,"icon":289,"path":290,"stem":291,"children":292},"TypeScript","i-simple-icons-typescript","\u002Ftu-hoc\u002Ftypescript","2.tu-hoc\u002F2.typescript\u002Findex",[293,294,297,301,306],{"title":288,"path":290,"stem":291,"icon":289},{"title":173,"path":295,"stem":296,"icon":176},"\u002Ftu-hoc\u002Ftypescript\u002Fgioi-thieu-cai-dat","2.tu-hoc\u002F2.typescript\u002F1.gioi-thieu-cai-dat",{"title":298,"path":299,"stem":300,"icon":81},"2. Type System","\u002Ftu-hoc\u002Ftypescript\u002Ftype-system","2.tu-hoc\u002F2.typescript\u002F2.type-system",{"title":302,"path":303,"stem":304,"icon":305},"3. Advanced types","\u002Ftu-hoc\u002Ftypescript\u002Fadvanced-types","2.tu-hoc\u002F2.typescript\u002F3.advanced-types","i-lucide-braces",{"title":307,"path":308,"stem":309,"icon":196},"4. Q và A phỏng vấn","\u002Ftu-hoc\u002Ftypescript\u002Fcau-hoi-phong-van","2.tu-hoc\u002F2.typescript\u002F4.cau-hoi-phong-van",{"title":311,"icon":81,"path":312,"stem":313,"children":314},"OOP","\u002Ftu-hoc\u002Foop","2.tu-hoc\u002F3.oop\u002Findex",[315,316,321,326,330],{"title":311,"path":312,"stem":313,"icon":81},{"title":317,"path":318,"stem":319,"icon":320},"1. Bốn tính chất","\u002Ftu-hoc\u002Foop\u002F4-tinh-chat","2.tu-hoc\u002F3.oop\u002F1.4-tinh-chat","i-lucide-circle-dot",{"title":322,"path":323,"stem":324,"icon":325},"2. SOLID","\u002Ftu-hoc\u002Foop\u002Fsolid","2.tu-hoc\u002F3.oop\u002F2.solid","i-lucide-shield",{"title":327,"path":328,"stem":329,"icon":106},"3. Design Pattern","\u002Ftu-hoc\u002Foop\u002Fdesign-pattern","2.tu-hoc\u002F3.oop\u002F3.design-pattern",{"title":307,"path":331,"stem":332,"icon":196},"\u002Ftu-hoc\u002Foop\u002Fcau-hoi-phong-van","2.tu-hoc\u002F3.oop\u002F4.cau-hoi-phong-van",{"title":334,"icon":305,"path":335,"stem":336,"children":337},"Generic","\u002Ftu-hoc\u002Fgeneric","2.tu-hoc\u002F4.generic\u002Findex",[338,339,344,349,354],{"title":334,"path":335,"stem":336,"icon":305},{"title":340,"path":341,"stem":342,"icon":343},"1. Khái niệm và cú pháp","\u002Ftu-hoc\u002Fgeneric\u002Fkhai-niem","2.tu-hoc\u002F4.generic\u002F1.khai-niem","i-lucide-book",{"title":345,"path":346,"stem":347,"icon":348},"2. Constraint và Variance","\u002Ftu-hoc\u002Fgeneric\u002Fconstraint-variance","2.tu-hoc\u002F4.generic\u002F2.constraint-variance","i-lucide-filter",{"title":350,"path":351,"stem":352,"icon":353},"3. C# vs TS","\u002Ftu-hoc\u002Fgeneric\u002Fso-sanh","2.tu-hoc\u002F4.generic\u002F3.so-sanh","i-lucide-git-compare",{"title":307,"path":355,"stem":356,"icon":196},"\u002Ftu-hoc\u002Fgeneric\u002Fcau-hoi-phong-van","2.tu-hoc\u002F4.generic\u002F4.cau-hoi-phong-van",{"title":358,"icon":359,"path":360,"stem":361,"children":362},"Nuxt 4","i-simple-icons-nuxt","\u002Ftu-hoc\u002Fnuxt-4","2.tu-hoc\u002F5.nuxt-4\u002Findex",[363,364,367,372,376,379],{"title":358,"path":360,"stem":361,"icon":359},{"title":173,"path":365,"stem":366,"icon":176},"\u002Ftu-hoc\u002Fnuxt-4\u002Fgioi-thieu-cai-dat","2.tu-hoc\u002F5.nuxt-4\u002F1.gioi-thieu-cai-dat",{"title":368,"path":369,"stem":370,"icon":371},"2. Routing và Rendering","\u002Ftu-hoc\u002Fnuxt-4\u002Frouting-rendering","2.tu-hoc\u002F5.nuxt-4\u002F2.routing-rendering","i-lucide-route",{"title":373,"path":374,"stem":375,"icon":91},"3. Data và Server","\u002Ftu-hoc\u002Fnuxt-4\u002Fdata-server","2.tu-hoc\u002F5.nuxt-4\u002F3.data-server",{"title":307,"path":377,"stem":378,"icon":196},"\u002Ftu-hoc\u002Fnuxt-4\u002Fcau-hoi-phong-van","2.tu-hoc\u002F5.nuxt-4\u002F4.cau-hoi-phong-van",{"title":380,"path":381,"stem":382,"icon":383},"5. Practical Todo App","\u002Ftu-hoc\u002Fnuxt-4\u002Fpractical-todo-app","2.tu-hoc\u002F5.nuxt-4\u002F5.practical-todo-app","i-lucide-check-square",{"title":385,"path":386,"stem":387,"children":388,"icon":390},"Tailwind CSS","\u002Ftu-hoc\u002Ftailwindcss","2.tu-hoc\u002F6.tailwindcss\u002Findex",[389,391,396,401,406,411,416],{"title":385,"path":386,"stem":387,"icon":390},"i-simple-icons-tailwindcss",{"title":392,"path":393,"stem":394,"icon":395},"1. Layout & Spacing","\u002Ftu-hoc\u002Ftailwindcss\u002Flayout-spacing","2.tu-hoc\u002F6.tailwindcss\u002F1.layout-spacing","i-lucide-layout",{"title":397,"path":398,"stem":399,"icon":400},"2. Typography & Colors","\u002Ftu-hoc\u002Ftailwindcss\u002Ftypography-colors","2.tu-hoc\u002F6.tailwindcss\u002F2.typography-colors","i-lucide-type",{"title":402,"path":403,"stem":404,"icon":405},"3. Interactive & Effects","\u002Ftu-hoc\u002Ftailwindcss\u002Finteractive-effects","2.tu-hoc\u002F6.tailwindcss\u002F3.interactive-effects","i-lucide-sparkles",{"title":407,"path":408,"stem":409,"icon":410},"4. Responsive & Dark Mode","\u002Ftu-hoc\u002Ftailwindcss\u002Fresponsive-darkmode","2.tu-hoc\u002F6.tailwindcss\u002F4.responsive-darkmode","i-lucide-monitor-smartphone",{"title":412,"path":413,"stem":414,"icon":415},"5. Customization & Theme","\u002Ftu-hoc\u002Ftailwindcss\u002Fcustomization","2.tu-hoc\u002F6.tailwindcss\u002F5.customization","i-lucide-settings-2",{"title":417,"path":418,"stem":419,"icon":181},"6. Practical Projects","\u002Ftu-hoc\u002Ftailwindcss\u002Fpractical-projects","2.tu-hoc\u002F6.tailwindcss\u002F6.practical-projects",{"id":421,"title":422,"body":423,"description":2787,"extension":2788,"links":2789,"meta":2790,"navigation":2791,"path":213,"seo":2792,"stem":214,"__hash__":2793},"docs\u002F2.tu-hoc\u002F1.database\u002F3.postgresql\u002F4.dac-thu-performance.md","Đặc thù PostgreSQL và Performance",{"type":424,"value":425,"toc":2743},"minimark",[426,431,440,521,627,632,647,651,680,710,714,721,750,764,783,787,802,805,809,813,861,865,978,982,1039,1043,1054,1061,1104,1109,1132,1158,1162,1244,1259,1263,1292,1319,1323,1368,1372,1416,1420,1500,1506,1510,1577,1581,1606,1609,1617,1620,1624,1638,1642,1653,1692,1696,1711,1715,1802,1806,1849,1867,1871,1886,1929,1933,2008,2012,2027,2048,2052,2142,2146,2150,2156,2160,2167,2196,2224,2246,2250,2261,2268,2316,2334,2340,2344,2351,2371,2375,2418,2422,2475,2488,2512,2516,2732,2739],[427,428,430],"h2",{"id":429},"_1-index-đa-dạng-nhất-trong-các-rdbms","1. Index — đa dạng nhất trong các RDBMS",[432,433,434,435,439],"p",{},"Postgres có ",[436,437,438],"strong",{},"6 loại index",", mỗi loại tối ưu cho usecase khác nhau:",[441,442,443,456],"table",{},[444,445,446],"thead",{},[447,448,449,453],"tr",{},[450,451,452],"th",{},"Loại",[450,454,455],{},"Khi nào",[457,458,459,471,481,491,501,511],"tbody",{},[447,460,461,468],{},[462,463,464,467],"td",{},[436,465,466],{},"B-tree"," (default)",[462,469,470],{},"Cột scalar, range query, equality",[447,472,473,478],{},[462,474,475],{},[436,476,477],{},"Hash",[462,479,480],{},"Equality thuần (= chỉ thôi)",[447,482,483,488],{},[462,484,485],{},[436,486,487],{},"GIN",[462,489,490],{},"Array, JSONB, full-text — multi-value indexing",[447,492,493,498],{},[462,494,495],{},[436,496,497],{},"GiST",[462,499,500],{},"Geometric, range, full-text",[447,502,503,508],{},[462,504,505],{},[436,506,507],{},"SP-GiST",[462,509,510],{},"Space-partitioned (quadtree, k-d tree)",[447,512,513,518],{},[462,514,515],{},[436,516,517],{},"BRIN",[462,519,520],{},"Bảng cực lớn, dữ liệu sắp xếp tự nhiên (log time-series)",[522,523,528],"pre",{"className":524,"code":525,"language":526,"meta":527,"style":527},"language-sql shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","-- B-tree (default)\nCREATE INDEX idx_orders_user ON orders (user_id);\n\n-- GIN cho JSONB\nCREATE INDEX idx_events_payload ON events USING GIN (payload);\n-- Hoặc compact hơn nếu chỉ dùng @>\nCREATE INDEX idx_events_payload ON events USING GIN (payload jsonb_path_ops);\n\n-- GIN cho array\nCREATE INDEX idx_posts_tags ON posts USING GIN (tags);\n\n-- GIST cho geometry \u002F range\nCREATE INDEX idx_locations_geom ON locations USING GIST (geom);\n\n-- BRIN cho time-series (cực gọn)\nCREATE INDEX idx_logs_created ON logs USING BRIN (created_at);\n","sql","",[529,530,531,539,545,552,558,564,570,576,581,587,593,598,604,610,615,621],"code",{"__ignoreMap":527},[532,533,536],"span",{"class":534,"line":535},"line",1,[532,537,538],{},"-- B-tree (default)\n",[532,540,542],{"class":534,"line":541},2,[532,543,544],{},"CREATE INDEX idx_orders_user ON orders (user_id);\n",[532,546,548],{"class":534,"line":547},3,[532,549,551],{"emptyLinePlaceholder":550},true,"\n",[532,553,555],{"class":534,"line":554},4,[532,556,557],{},"-- GIN cho JSONB\n",[532,559,561],{"class":534,"line":560},5,[532,562,563],{},"CREATE INDEX idx_events_payload ON events USING GIN (payload);\n",[532,565,567],{"class":534,"line":566},6,[532,568,569],{},"-- Hoặc compact hơn nếu chỉ dùng @>\n",[532,571,573],{"class":534,"line":572},7,[532,574,575],{},"CREATE INDEX idx_events_payload ON events USING GIN (payload jsonb_path_ops);\n",[532,577,579],{"class":534,"line":578},8,[532,580,551],{"emptyLinePlaceholder":550},[532,582,584],{"class":534,"line":583},9,[532,585,586],{},"-- GIN cho array\n",[532,588,590],{"class":534,"line":589},10,[532,591,592],{},"CREATE INDEX idx_posts_tags ON posts USING GIN (tags);\n",[532,594,596],{"class":534,"line":595},11,[532,597,551],{"emptyLinePlaceholder":550},[532,599,601],{"class":534,"line":600},12,[532,602,603],{},"-- GIST cho geometry \u002F range\n",[532,605,607],{"class":534,"line":606},13,[532,608,609],{},"CREATE INDEX idx_locations_geom ON locations USING GIST (geom);\n",[532,611,613],{"class":534,"line":612},14,[532,614,551],{"emptyLinePlaceholder":550},[532,616,618],{"class":534,"line":617},15,[532,619,620],{},"-- BRIN cho time-series (cực gọn)\n",[532,622,624],{"class":534,"line":623},16,[532,625,626],{},"CREATE INDEX idx_logs_created ON logs USING BRIN (created_at);\n",[628,629,631],"h3",{"id":630},"partial-index","Partial index",[522,633,635],{"className":524,"code":634,"language":526,"meta":527,"style":527},"-- Chỉ index khách hàng active — index nhỏ + nhanh hơn\nCREATE INDEX idx_users_active_email ON users (email) WHERE status = 'active';\n",[529,636,637,642],{"__ignoreMap":527},[532,638,639],{"class":534,"line":535},[532,640,641],{},"-- Chỉ index khách hàng active — index nhỏ + nhanh hơn\n",[532,643,644],{"class":534,"line":541},[532,645,646],{},"CREATE INDEX idx_users_active_email ON users (email) WHERE status = 'active';\n",[628,648,650],{"id":649},"expression-index","Expression index",[522,652,654],{"className":524,"code":653,"language":526,"meta":527,"style":527},"-- Index trên expression — giải bài \"non-sargable\" hay gặp\nCREATE INDEX idx_users_lower_email ON users (LOWER(email));\n\n-- Query có thể dùng index này:\nSELECT * FROM users WHERE LOWER(email) = 'a@b.com';\n",[529,655,656,661,666,670,675],{"__ignoreMap":527},[532,657,658],{"class":534,"line":535},[532,659,660],{},"-- Index trên expression — giải bài \"non-sargable\" hay gặp\n",[532,662,663],{"class":534,"line":541},[532,664,665],{},"CREATE INDEX idx_users_lower_email ON users (LOWER(email));\n",[532,667,668],{"class":534,"line":547},[532,669,551],{"emptyLinePlaceholder":550},[532,671,672],{"class":534,"line":554},[532,673,674],{},"-- Query có thể dùng index này:\n",[532,676,677],{"class":534,"line":560},[532,678,679],{},"SELECT * FROM users WHERE LOWER(email) = 'a@b.com';\n",[681,682,685,700],"callout",{"color":683,"icon":684},"warning","i-lucide-star",[432,686,687,688,691,692],{},"⭐ ",[436,689,690],{},"Câu PV hot — đặc thù Postgres:"," ",[693,694,695,696,699],"em",{},"\"Cách giải ",[529,697,698],{},"WHERE LOWER(email) = ?"," chậm?\"",[701,702,703],"blockquote",{},[432,704,705,706,709],{},"\"Tạo expression index ",[529,707,708],{},"CREATE INDEX ... ON users (LOWER(email))",". Postgres dùng được index trên expression — SQL Server cần computed column PERSISTED, MySQL cần computed column.\"",[628,711,713],{"id":712},"b-tree-skip-scan-postgres-18","B-tree Skip Scan (Postgres 18)",[432,715,716,717,720],{},"Postgres 18+ planner hỗ trợ ",[436,718,719],{},"B-tree Skip Scan"," — dùng composite index hiệu quả ngay cả khi filter thiếu left-most column:",[522,722,724],{"className":524,"code":723,"language":526,"meta":527,"style":527},"CREATE INDEX idx_a_b ON t (a, b);\n\n-- Pre-18: không dùng được idx_a_b vì thiếu điều kiện trên 'a'\n-- PG 18+: planner có thể Skip Scan — duyệt distinct 'a', tìm 'b' trong từng group\nSELECT * FROM t WHERE b = 10;\n",[529,725,726,731,735,740,745],{"__ignoreMap":527},[532,727,728],{"class":534,"line":535},[532,729,730],{},"CREATE INDEX idx_a_b ON t (a, b);\n",[532,732,733],{"class":534,"line":541},[532,734,551],{"emptyLinePlaceholder":550},[532,736,737],{"class":534,"line":547},[532,738,739],{},"-- Pre-18: không dùng được idx_a_b vì thiếu điều kiện trên 'a'\n",[532,741,742],{"class":534,"line":554},[532,743,744],{},"-- PG 18+: planner có thể Skip Scan — duyệt distinct 'a', tìm 'b' trong từng group\n",[532,746,747],{"class":534,"line":560},[532,748,749],{},"SELECT * FROM t WHERE b = 10;\n",[432,751,752,753,756,757,760,761,763],{},"Cơ chế: planner duyệt qua các distinct value của cột ",[529,754,755],{},"a"," trong index, với mỗi value tìm ",[529,758,759],{},"b = 10"," bên trong. Hiệu quả khi số distinct value của ",[529,762,755],{}," ít.",[681,765,687,767,770,771,774,775,778,779,782],{"color":766,"icon":684},"primary",[436,768,769],{},"Lưu ý:"," Skip Scan không thay thế được index riêng trên ",[529,772,773],{},"b",". Chỉ hiệu quả khi cardinality của left-most column thấp. Nếu query ",[529,776,777],{},"WHERE b = 10"," thường xuyên → vẫn nên tạo index riêng ",[529,780,781],{},"ON t (b)",".",[628,784,786],{"id":785},"concurrently-tạo-index-không-lock","CONCURRENTLY — tạo index không lock",[522,788,790],{"className":524,"code":789,"language":526,"meta":527,"style":527},"-- Production: dùng CONCURRENTLY để không block write\nCREATE INDEX CONCURRENTLY idx_orders_status ON orders(status);\n",[529,791,792,797],{"__ignoreMap":527},[532,793,794],{"class":534,"line":535},[532,795,796],{},"-- Production: dùng CONCURRENTLY để không block write\n",[532,798,799],{"class":534,"line":541},[532,800,801],{},"CREATE INDEX CONCURRENTLY idx_orders_status ON orders(status);\n",[432,803,804],{},"Chậm hơn nhưng không lock bảng. Cần thiết cho live DB.",[427,806,808],{"id":807},"_2-jsonb-sức-mạnh-postgres","2. JSONB — sức mạnh Postgres",[628,810,812],{"id":811},"index-strategy","Index strategy",[522,814,816],{"className":524,"code":815,"language":526,"meta":527,"style":527},"-- Toàn bộ JSONB\nCREATE INDEX idx_payload ON events USING GIN (payload);\n\n-- Chỉ key cụ thể (nhỏ hơn)\nCREATE INDEX idx_payload_type ON events USING BTREE ((payload->>'type'));\n\n-- Query path\nCREATE INDEX idx_payload_user_id\n    ON events USING BTREE ((payload->'user'->>'id'));\n",[529,817,818,823,828,832,837,842,846,851,856],{"__ignoreMap":527},[532,819,820],{"class":534,"line":535},[532,821,822],{},"-- Toàn bộ JSONB\n",[532,824,825],{"class":534,"line":541},[532,826,827],{},"CREATE INDEX idx_payload ON events USING GIN (payload);\n",[532,829,830],{"class":534,"line":547},[532,831,551],{"emptyLinePlaceholder":550},[532,833,834],{"class":534,"line":554},[532,835,836],{},"-- Chỉ key cụ thể (nhỏ hơn)\n",[532,838,839],{"class":534,"line":560},[532,840,841],{},"CREATE INDEX idx_payload_type ON events USING BTREE ((payload->>'type'));\n",[532,843,844],{"class":534,"line":566},[532,845,551],{"emptyLinePlaceholder":550},[532,847,848],{"class":534,"line":572},[532,849,850],{},"-- Query path\n",[532,852,853],{"class":534,"line":578},[532,854,855],{},"CREATE INDEX idx_payload_user_id\n",[532,857,858],{"class":534,"line":583},[532,859,860],{},"    ON events USING BTREE ((payload->'user'->>'id'));\n",[628,862,864],{"id":863},"operator-quan-trọng","Operator quan trọng",[441,866,867,880],{},[444,868,869],{},[447,870,871,874,877],{},[450,872,873],{},"Operator",[450,875,876],{},"Ý nghĩa",[450,878,879],{},"Index",[457,881,882,895,907,919,931,943,954,966],{},[447,883,884,889,892],{},[462,885,886],{},[529,887,888],{},"->",[462,890,891],{},"Get JSONB",[462,893,894],{},"–",[447,896,897,902,905],{},[462,898,899],{},[529,900,901],{},"->>",[462,903,904],{},"Get TEXT",[462,906,466],{},[447,908,909,914,917],{},[462,910,911],{},[529,912,913],{},"@>",[462,915,916],{},"Contains",[462,918,487],{},[447,920,921,926,929],{},[462,922,923],{},[529,924,925],{},"\u003C@",[462,927,928],{},"Contained by",[462,930,487],{},[447,932,933,938,941],{},[462,934,935],{},[529,936,937],{},"?",[462,939,940],{},"Key exists",[462,942,487],{},[447,944,945,948,951],{},[462,946,947],{},"`?",[462,949,950],{},"`",[462,952,953],{},"Any key",[447,955,956,961,964],{},[462,957,958],{},[529,959,960],{},"?&",[462,962,963],{},"All keys",[462,965,487],{},[447,967,968,973,976],{},[462,969,970],{},[529,971,972],{},"@?",[462,974,975],{},"JSON path matches",[462,977,487],{},[628,979,981],{"id":980},"update-jsonb","Update JSONB",[522,983,985],{"className":524,"code":984,"language":526,"meta":527,"style":527},"-- jsonb_set\nUPDATE events\nSET payload = jsonb_set(payload, '{processed}', 'true', true)\nWHERE id = 1;\n\n-- Merge (||)\nUPDATE events\nSET payload = payload || '{\"reviewed\": true}'::jsonb;\n\n-- Remove key (-)\nUPDATE events SET payload = payload - 'temp_field';\n",[529,986,987,992,997,1002,1007,1011,1016,1020,1025,1029,1034],{"__ignoreMap":527},[532,988,989],{"class":534,"line":535},[532,990,991],{},"-- jsonb_set\n",[532,993,994],{"class":534,"line":541},[532,995,996],{},"UPDATE events\n",[532,998,999],{"class":534,"line":547},[532,1000,1001],{},"SET payload = jsonb_set(payload, '{processed}', 'true', true)\n",[532,1003,1004],{"class":534,"line":554},[532,1005,1006],{},"WHERE id = 1;\n",[532,1008,1009],{"class":534,"line":560},[532,1010,551],{"emptyLinePlaceholder":550},[532,1012,1013],{"class":534,"line":566},[532,1014,1015],{},"-- Merge (||)\n",[532,1017,1018],{"class":534,"line":572},[532,1019,996],{},[532,1021,1022],{"class":534,"line":578},[532,1023,1024],{},"SET payload = payload || '{\"reviewed\": true}'::jsonb;\n",[532,1026,1027],{"class":534,"line":583},[532,1028,551],{"emptyLinePlaceholder":550},[532,1030,1031],{"class":534,"line":589},[532,1032,1033],{},"-- Remove key (-)\n",[532,1035,1036],{"class":534,"line":595},[532,1037,1038],{},"UPDATE events SET payload = payload - 'temp_field';\n",[628,1040,1042],{"id":1041},"json-copy-to-postgres-19","JSON COPY TO — Postgres 19",[432,1044,1045,1046,1049,1050,1053],{},"Trước PG 19, export JSON cần ",[529,1047,1048],{},"row_to_json()"," + ",[529,1051,1052],{},"json_agg()"," — build toàn bộ JSON array trong memory rồi mới trả về. Với bảng hàng triệu row, query dễ OOM.",[432,1055,1056,1057,1060],{},"PG 19 hỗ trợ native JSON export qua ",[529,1058,1059],{},"COPY TO",":",[522,1062,1064],{"className":524,"code":1063,"language":526,"meta":527,"style":527},"-- NDJSON output (default) — streaming từng row, memory-efficient\nCOPY users TO STDOUT WITH (FORMAT JSON);\n\n-- JSON array output — [] bao toàn bộ\nCOPY users TO STDOUT WITH (FORMAT JSON, FORCE_ARRAY);\n\n-- Có thể pipe thẳng vào file\nCOPY users TO '\u002Ftmp\u002Fusers.json' WITH (FORMAT JSON);\n",[529,1065,1066,1071,1076,1080,1085,1090,1094,1099],{"__ignoreMap":527},[532,1067,1068],{"class":534,"line":535},[532,1069,1070],{},"-- NDJSON output (default) — streaming từng row, memory-efficient\n",[532,1072,1073],{"class":534,"line":541},[532,1074,1075],{},"COPY users TO STDOUT WITH (FORMAT JSON);\n",[532,1077,1078],{"class":534,"line":547},[532,1079,551],{"emptyLinePlaceholder":550},[532,1081,1082],{"class":534,"line":554},[532,1083,1084],{},"-- JSON array output — [] bao toàn bộ\n",[532,1086,1087],{"class":534,"line":560},[532,1088,1089],{},"COPY users TO STDOUT WITH (FORMAT JSON, FORCE_ARRAY);\n",[532,1091,1092],{"class":534,"line":566},[532,1093,551],{"emptyLinePlaceholder":550},[532,1095,1096],{"class":534,"line":572},[532,1097,1098],{},"-- Có thể pipe thẳng vào file\n",[532,1100,1101],{"class":534,"line":578},[532,1102,1103],{},"COPY users TO '\u002Ftmp\u002Fusers.json' WITH (FORMAT JSON);\n",[432,1105,1106],{},[436,1107,1108],{},"Ưu điểm:",[1110,1111,1112,1116,1122],"ul",{},[1113,1114,1115],"li",{},"Streaming: không build toàn bộ JSON trong memory — an toàn cho bảng lớn.",[1113,1117,1118,1119,1121],{},"Nhanh hơn ",[529,1120,1052],{}," nhiều lần do không cần aggregate.",[1113,1123,1124,1125,1127,1128,1131],{},"PG 19 còn cho phép ",[529,1126,1059],{}," trực tiếp trên ",[436,1129,1130],{},"partitioned table"," (trước đây phải COPY từng partition).",[681,1133,1134,1142],{"color":683,"icon":684},[432,1135,687,1136,691,1139],{},[436,1137,1138],{},"Câu PV:",[693,1140,1141],{},"\"Làm sao export JSON từ Postgres hiệu quả cho bảng 50M row?\"",[701,1143,1144],{},[432,1145,1146,1147,1150,1151,1153,1154,1157],{},"\"Dùng ",[529,1148,1149],{},"COPY TO STDOUT WITH (FORMAT JSON)"," (PG 19+) — streaming từng row ra NDJSON, không build toàn bộ JSON trong memory như ",[529,1152,1052],{}," cũ. Có thể pipe thẳng ra file hoặc HTTP response. Hoặc ",[529,1155,1156],{},"FORCE_ARRAY"," nếu cần JSON array.\"",[427,1159,1161],{"id":1160},"_3-array-không-cần-bảng-phụ","3. Array — không cần bảng phụ",[522,1163,1165],{"className":524,"code":1164,"language":526,"meta":527,"style":527},"CREATE TABLE posts (\n    id BIGSERIAL PRIMARY KEY,\n    tags TEXT[] DEFAULT '{}'\n);\n\n-- Operator\nSELECT * FROM posts WHERE tags @> ARRAY['vue'];        -- contains\nSELECT * FROM posts WHERE tags && ARRAY['vue','react']; -- overlap\nSELECT * FROM posts WHERE 'vue' = ANY(tags);\nSELECT * FROM posts WHERE NOT ('react' = ALL(tags));\n\n-- unnest — biến array thành rows\nSELECT unnest(tags) AS tag FROM posts WHERE id = 1;\n\n-- Aggregate ngược lại\nSELECT array_agg(name ORDER BY name) FROM users;\n",[529,1166,1167,1172,1177,1182,1187,1191,1196,1201,1206,1211,1216,1220,1225,1230,1234,1239],{"__ignoreMap":527},[532,1168,1169],{"class":534,"line":535},[532,1170,1171],{},"CREATE TABLE posts (\n",[532,1173,1174],{"class":534,"line":541},[532,1175,1176],{},"    id BIGSERIAL PRIMARY KEY,\n",[532,1178,1179],{"class":534,"line":547},[532,1180,1181],{},"    tags TEXT[] DEFAULT '{}'\n",[532,1183,1184],{"class":534,"line":554},[532,1185,1186],{},");\n",[532,1188,1189],{"class":534,"line":560},[532,1190,551],{"emptyLinePlaceholder":550},[532,1192,1193],{"class":534,"line":566},[532,1194,1195],{},"-- Operator\n",[532,1197,1198],{"class":534,"line":572},[532,1199,1200],{},"SELECT * FROM posts WHERE tags @> ARRAY['vue'];        -- contains\n",[532,1202,1203],{"class":534,"line":578},[532,1204,1205],{},"SELECT * FROM posts WHERE tags && ARRAY['vue','react']; -- overlap\n",[532,1207,1208],{"class":534,"line":583},[532,1209,1210],{},"SELECT * FROM posts WHERE 'vue' = ANY(tags);\n",[532,1212,1213],{"class":534,"line":589},[532,1214,1215],{},"SELECT * FROM posts WHERE NOT ('react' = ALL(tags));\n",[532,1217,1218],{"class":534,"line":595},[532,1219,551],{"emptyLinePlaceholder":550},[532,1221,1222],{"class":534,"line":600},[532,1223,1224],{},"-- unnest — biến array thành rows\n",[532,1226,1227],{"class":534,"line":606},[532,1228,1229],{},"SELECT unnest(tags) AS tag FROM posts WHERE id = 1;\n",[532,1231,1232],{"class":534,"line":612},[532,1233,551],{"emptyLinePlaceholder":550},[532,1235,1236],{"class":534,"line":617},[532,1237,1238],{},"-- Aggregate ngược lại\n",[532,1240,1241],{"class":534,"line":623},[532,1242,1243],{},"SELECT array_agg(name ORDER BY name) FROM users;\n",[681,1245,1246,1251],{"color":766,"icon":684},[432,1247,687,1248],{},[436,1249,1250],{},"Lưu khi nào dùng array vs bảng phụ:",[1110,1252,1253,1256],{},[1113,1254,1255],{},"Array OK khi: số phần tử ít (\u003C 100), không cần JOIN\u002Findex từng giá trị riêng, atomic.",[1113,1257,1258],{},"Bảng phụ khi: cần FK, query phức tạp theo từng phần tử, set lớn.",[427,1260,1262],{"id":1261},"_4-uuid-postgres-18-mới-có-uuidv7","4. UUID — Postgres 18 mới có uuidv7()",[522,1264,1266],{"className":524,"code":1265,"language":526,"meta":527,"style":527},"CREATE TABLE accounts (\n    id UUID PRIMARY KEY DEFAULT uuidv7(),     -- 18+\n    -- DEFAULT gen_random_uuid() cho pre-18 (v4 random)\n    email TEXT\n);\n",[529,1267,1268,1273,1278,1283,1288],{"__ignoreMap":527},[532,1269,1270],{"class":534,"line":535},[532,1271,1272],{},"CREATE TABLE accounts (\n",[532,1274,1275],{"class":534,"line":541},[532,1276,1277],{},"    id UUID PRIMARY KEY DEFAULT uuidv7(),     -- 18+\n",[532,1279,1280],{"class":534,"line":547},[532,1281,1282],{},"    -- DEFAULT gen_random_uuid() cho pre-18 (v4 random)\n",[532,1284,1285],{"class":534,"line":554},[532,1286,1287],{},"    email TEXT\n",[532,1289,1290],{"class":534,"line":560},[532,1291,1186],{},[681,1293,1294,1299,1313],{"color":683,"icon":684},[432,1295,687,1296],{},[436,1297,1298],{},"UUIDv7 vs UUIDv4 — vì sao nên chuyển:",[432,1300,1301,1302,1305,1306,1309,1310],{},"UUIDv7 chứa ",[436,1303,1304],{},"timestamp ở đầu"," → sort tự nhiên theo thời gian. Insert vào B-tree index ",[436,1307,1308],{},"không bị page split"," như UUIDv4 random. ",[436,1311,1312],{},"Index nhỏ hơn, write nhanh hơn, query range theo time dễ.",[432,1314,1315,1316,782],{},"→ Cho mọi project mới trên Postgres 18+, chọn ",[529,1317,1318],{},"uuidv7()",[427,1320,1322],{"id":1321},"_5-extension-feature-qua-plugin","5. Extension — feature qua plugin",[522,1324,1326],{"className":524,"code":1325,"language":526,"meta":527,"style":527},"-- Top extension dev thường dùng\nCREATE EXTENSION IF NOT EXISTS pg_trgm;            -- fuzzy search, similarity\nCREATE EXTENSION IF NOT EXISTS pgcrypto;           -- crypto, hash\nCREATE EXTENSION IF NOT EXISTS postgis;            -- GIS, geometry\nCREATE EXTENSION IF NOT EXISTS pg_stat_statements; -- query monitoring\nCREATE EXTENSION IF NOT EXISTS vector;             -- AI embedding (pgvector)\nCREATE EXTENSION IF NOT EXISTS timescaledb;        -- time-series\nCREATE EXTENSION IF NOT EXISTS unaccent;           -- bỏ dấu tiếng Việt\n",[529,1327,1328,1333,1338,1343,1348,1353,1358,1363],{"__ignoreMap":527},[532,1329,1330],{"class":534,"line":535},[532,1331,1332],{},"-- Top extension dev thường dùng\n",[532,1334,1335],{"class":534,"line":541},[532,1336,1337],{},"CREATE EXTENSION IF NOT EXISTS pg_trgm;            -- fuzzy search, similarity\n",[532,1339,1340],{"class":534,"line":547},[532,1341,1342],{},"CREATE EXTENSION IF NOT EXISTS pgcrypto;           -- crypto, hash\n",[532,1344,1345],{"class":534,"line":554},[532,1346,1347],{},"CREATE EXTENSION IF NOT EXISTS postgis;            -- GIS, geometry\n",[532,1349,1350],{"class":534,"line":560},[532,1351,1352],{},"CREATE EXTENSION IF NOT EXISTS pg_stat_statements; -- query monitoring\n",[532,1354,1355],{"class":534,"line":566},[532,1356,1357],{},"CREATE EXTENSION IF NOT EXISTS vector;             -- AI embedding (pgvector)\n",[532,1359,1360],{"class":534,"line":572},[532,1361,1362],{},"CREATE EXTENSION IF NOT EXISTS timescaledb;        -- time-series\n",[532,1364,1365],{"class":534,"line":578},[532,1366,1367],{},"CREATE EXTENSION IF NOT EXISTS unaccent;           -- bỏ dấu tiếng Việt\n",[628,1369,1371],{"id":1370},"pg_trgm-fuzzy-search","pg_trgm — fuzzy search",[522,1373,1375],{"className":524,"code":1374,"language":526,"meta":527,"style":527},"CREATE EXTENSION pg_trgm;\nCREATE INDEX idx_products_name_trgm ON products USING GIN (name gin_trgm_ops);\n\n-- Tìm gần đúng\nSELECT name, similarity(name, 'iPone') AS sim\nFROM products\nWHERE name % 'iPone'                  -- threshold default 0.3\nORDER BY sim DESC;\n",[529,1376,1377,1382,1387,1391,1396,1401,1406,1411],{"__ignoreMap":527},[532,1378,1379],{"class":534,"line":535},[532,1380,1381],{},"CREATE EXTENSION pg_trgm;\n",[532,1383,1384],{"class":534,"line":541},[532,1385,1386],{},"CREATE INDEX idx_products_name_trgm ON products USING GIN (name gin_trgm_ops);\n",[532,1388,1389],{"class":534,"line":547},[532,1390,551],{"emptyLinePlaceholder":550},[532,1392,1393],{"class":534,"line":554},[532,1394,1395],{},"-- Tìm gần đúng\n",[532,1397,1398],{"class":534,"line":560},[532,1399,1400],{},"SELECT name, similarity(name, 'iPone') AS sim\n",[532,1402,1403],{"class":534,"line":566},[532,1404,1405],{},"FROM products\n",[532,1407,1408],{"class":534,"line":572},[532,1409,1410],{},"WHERE name % 'iPone'                  -- threshold default 0.3\n",[532,1412,1413],{"class":534,"line":578},[532,1414,1415],{},"ORDER BY sim DESC;\n",[628,1417,1419],{"id":1418},"pgvector-ai-embedding","pgvector — AI embedding",[522,1421,1423],{"className":524,"code":1422,"language":526,"meta":527,"style":527},"CREATE EXTENSION vector;\n\nCREATE TABLE docs (\n    id BIGSERIAL PRIMARY KEY,\n    content TEXT,\n    embedding vector(1536)            -- OpenAI text-embedding-3-small\n);\n\n-- IVFFlat hoặc HNSW index\nCREATE INDEX ON docs USING hnsw (embedding vector_cosine_ops);\n\n-- Semantic search\nSELECT id, content, embedding \u003C=> '[...]'::vector AS distance\nFROM docs\nORDER BY embedding \u003C=> '[...]'::vector\nLIMIT 5;\n",[529,1424,1425,1430,1434,1439,1443,1448,1453,1457,1461,1466,1471,1475,1480,1485,1490,1495],{"__ignoreMap":527},[532,1426,1427],{"class":534,"line":535},[532,1428,1429],{},"CREATE EXTENSION vector;\n",[532,1431,1432],{"class":534,"line":541},[532,1433,551],{"emptyLinePlaceholder":550},[532,1435,1436],{"class":534,"line":547},[532,1437,1438],{},"CREATE TABLE docs (\n",[532,1440,1441],{"class":534,"line":554},[532,1442,1176],{},[532,1444,1445],{"class":534,"line":560},[532,1446,1447],{},"    content TEXT,\n",[532,1449,1450],{"class":534,"line":566},[532,1451,1452],{},"    embedding vector(1536)            -- OpenAI text-embedding-3-small\n",[532,1454,1455],{"class":534,"line":572},[532,1456,1186],{},[532,1458,1459],{"class":534,"line":578},[532,1460,551],{"emptyLinePlaceholder":550},[532,1462,1463],{"class":534,"line":583},[532,1464,1465],{},"-- IVFFlat hoặc HNSW index\n",[532,1467,1468],{"class":534,"line":589},[532,1469,1470],{},"CREATE INDEX ON docs USING hnsw (embedding vector_cosine_ops);\n",[532,1472,1473],{"class":534,"line":595},[532,1474,551],{"emptyLinePlaceholder":550},[532,1476,1477],{"class":534,"line":600},[532,1478,1479],{},"-- Semantic search\n",[532,1481,1482],{"class":534,"line":606},[532,1483,1484],{},"SELECT id, content, embedding \u003C=> '[...]'::vector AS distance\n",[532,1486,1487],{"class":534,"line":612},[532,1488,1489],{},"FROM docs\n",[532,1491,1492],{"class":534,"line":617},[532,1493,1494],{},"ORDER BY embedding \u003C=> '[...]'::vector\n",[532,1496,1497],{"class":534,"line":623},[532,1498,1499],{},"LIMIT 5;\n",[681,1501,687,1502,1505],{"color":766,"icon":684},[436,1503,1504],{},"Trend 2025–2026:"," pgvector là chuẩn de-facto cho RAG (Retrieval Augmented Generation). Postgres + pgvector = vector DB không cần Pinecone\u002FWeaviate riêng.",[427,1507,1509],{"id":1508},"_6-temporal-table-mô-phỏng-postgres-18-temporal-constraints","6. Temporal table (mô phỏng) + Postgres 18 temporal constraints",[522,1511,1513],{"className":524,"code":1512,"language":526,"meta":527,"style":527},"-- 18+: PK temporal — không trùng theo time range\nCREATE TABLE room_reservations (\n    room_id INT,\n    valid_during TSRANGE,\n    PRIMARY KEY (room_id, valid_during WITHOUT OVERLAPS)\n);\n\n-- 18+: FK temporal\nCREATE TABLE bookings (\n    ... ,\n    FOREIGN KEY (room_id, period) REFERENCES room_reservations\n        (room_id, valid_during) PERIOD (period)\n);\n",[529,1514,1515,1520,1525,1530,1535,1540,1544,1548,1553,1558,1563,1568,1573],{"__ignoreMap":527},[532,1516,1517],{"class":534,"line":535},[532,1518,1519],{},"-- 18+: PK temporal — không trùng theo time range\n",[532,1521,1522],{"class":534,"line":541},[532,1523,1524],{},"CREATE TABLE room_reservations (\n",[532,1526,1527],{"class":534,"line":547},[532,1528,1529],{},"    room_id INT,\n",[532,1531,1532],{"class":534,"line":554},[532,1533,1534],{},"    valid_during TSRANGE,\n",[532,1536,1537],{"class":534,"line":560},[532,1538,1539],{},"    PRIMARY KEY (room_id, valid_during WITHOUT OVERLAPS)\n",[532,1541,1542],{"class":534,"line":566},[532,1543,1186],{},[532,1545,1546],{"class":534,"line":572},[532,1547,551],{"emptyLinePlaceholder":550},[532,1549,1550],{"class":534,"line":578},[532,1551,1552],{},"-- 18+: FK temporal\n",[532,1554,1555],{"class":534,"line":583},[532,1556,1557],{},"CREATE TABLE bookings (\n",[532,1559,1560],{"class":534,"line":589},[532,1561,1562],{},"    ... ,\n",[532,1564,1565],{"class":534,"line":595},[532,1566,1567],{},"    FOREIGN KEY (room_id, period) REFERENCES room_reservations\n",[532,1569,1570],{"class":534,"line":600},[532,1571,1572],{},"        (room_id, valid_during) PERIOD (period)\n",[532,1574,1575],{"class":534,"line":606},[532,1576,1186],{},[427,1578,1580],{"id":1579},"_7-explain-đọc-plan","7. EXPLAIN — đọc plan",[522,1582,1584],{"className":524,"code":1583,"language":526,"meta":527,"style":527},"EXPLAIN (ANALYZE, BUFFERS, VERBOSE)\nSELECT * FROM orders\nWHERE user_id = 1 AND status = 'paid'\nORDER BY created_at DESC LIMIT 10;\n",[529,1585,1586,1591,1596,1601],{"__ignoreMap":527},[532,1587,1588],{"class":534,"line":535},[532,1589,1590],{},"EXPLAIN (ANALYZE, BUFFERS, VERBOSE)\n",[532,1592,1593],{"class":534,"line":541},[532,1594,1595],{},"SELECT * FROM orders\n",[532,1597,1598],{"class":534,"line":547},[532,1599,1600],{},"WHERE user_id = 1 AND status = 'paid'\n",[532,1602,1603],{"class":534,"line":554},[532,1604,1605],{},"ORDER BY created_at DESC LIMIT 10;\n",[432,1607,1608],{},"Output example:",[522,1610,1615],{"className":1611,"code":1613,"language":1614},[1612],"language-text","Limit  (cost=0.42..8.45 rows=10 width=120) (actual time=0.05..0.10 rows=10 loops=1)\n  ->  Index Scan using idx_orders_user_created on orders\n       (cost=0.42..234.50 rows=300 width=120)\n       Index Cond: (user_id = 1)\n       Filter: (status = 'paid')\n       Rows Removed by Filter: 50\n       Buffers: shared hit=15\nPlanning Time: 0.15 ms\nExecution Time: 0.13 ms\n","text",[529,1616,1613],{"__ignoreMap":527},[432,1618,1619],{},"Đọc top-down: outer node nhận row từ inner node.",[628,1621,1623],{"id":1622},"tools-để-visualize","Tools để visualize",[1110,1625,1626,1632],{},[1113,1627,1628,1631],{},[436,1629,1630],{},"explain.dalibo.com"," — paste plan, được tree đẹp.",[1113,1633,1634,1637],{},[436,1635,1636],{},"pgAdmin"," — built-in Plan Explorer.",[427,1639,1641],{"id":1640},"_8-pg_plan_advice-query-plan-hints-postgres-19","8. pg_plan_advice — Query Plan Hints (Postgres 19)",[432,1643,1644,1645,1648,1649,1652],{},"Đây là một trong những tính năng ",[436,1646,1647],{},"major nhất của PG 19",": official plan hints qua contrib module ",[529,1650,1651],{},"pg_plan_advice",". Không giống Oracle\u002FMySQL nhúng hint vào SQL comment — Postgres để hint trong GUC setting, SQL code vẫn sạch.",[522,1654,1656],{"className":524,"code":1655,"language":526,"meta":527,"style":527},"-- Bước 1: Generate advice từ plan hiện tại\nEXPLAIN (COSTS OFF, PLAN_ADVICE)\nSELECT * FROM orders o JOIN customers c ON o.cust_id = c.id;\n-- Output example: JOIN_ORDER(o c)  HASH_JOIN(c)  SEQ_SCAN(o c)\n\n-- Bước 2: Lock plan theo advice\nSET pg_plan_advice.advice = 'JOIN_ORDER(o c) HASH_JOIN(c) SEQ_SCAN(o c)';\n",[529,1657,1658,1663,1668,1673,1678,1682,1687],{"__ignoreMap":527},[532,1659,1660],{"class":534,"line":535},[532,1661,1662],{},"-- Bước 1: Generate advice từ plan hiện tại\n",[532,1664,1665],{"class":534,"line":541},[532,1666,1667],{},"EXPLAIN (COSTS OFF, PLAN_ADVICE)\n",[532,1669,1670],{"class":534,"line":547},[532,1671,1672],{},"SELECT * FROM orders o JOIN customers c ON o.cust_id = c.id;\n",[532,1674,1675],{"class":534,"line":554},[532,1676,1677],{},"-- Output example: JOIN_ORDER(o c)  HASH_JOIN(c)  SEQ_SCAN(o c)\n",[532,1679,1680],{"class":534,"line":560},[532,1681,551],{"emptyLinePlaceholder":550},[532,1683,1684],{"class":534,"line":566},[532,1685,1686],{},"-- Bước 2: Lock plan theo advice\n",[532,1688,1689],{"class":534,"line":572},[532,1690,1691],{},"SET pg_plan_advice.advice = 'JOIN_ORDER(o c) HASH_JOIN(c) SEQ_SCAN(o c)';\n",[628,1693,1695],{"id":1694},"cơ-chế","Cơ chế",[1110,1697,1698,1701,1708],{},[1113,1699,1700],{},"Planner tự generate \"advice string\" từ plan nó chọn → bạn có thể review rồi lock.",[1113,1702,1703,1704,1707],{},"Module có ",[436,1705,1706],{},"feedback mechanism",": log cho biết hint có được honor không và vì sao bị bỏ qua.",[1113,1709,1710],{},"Hint nằm ngoài SQL → đổi hint không cần deploy code, SQL portable giữa các môi trường.",[628,1712,1714],{"id":1713},"so-sánh-với-oraclemysql-hints","So sánh với Oracle\u002FMySQL hints",[441,1716,1717,1732],{},[444,1718,1719],{},[447,1720,1721,1723,1726,1729],{},[450,1722],{},[450,1724,1725],{},"pg_plan_advice (PG 19)",[450,1727,1728],{},"Oracle hints",[450,1730,1731],{},"MySQL hints",[457,1733,1734,1752,1765,1776,1790],{},[447,1735,1736,1739,1742,1748],{},[462,1737,1738],{},"Vị trí hint",[462,1740,1741],{},"GUC setting",[462,1743,1744,1745],{},"SQL comment ",[529,1746,1747],{},"\u002F*+ *\u002F",[462,1749,1744,1750],{},[529,1751,1747],{},[447,1753,1754,1757,1760,1763],{},[462,1755,1756],{},"SQL có sạch không",[462,1758,1759],{},"Có",[462,1761,1762],{},"Không",[462,1764,1762],{},[447,1766,1767,1770,1772,1774],{},[462,1768,1769],{},"Đổi hint cần deploy",[462,1771,1762],{},[462,1773,1759],{},[462,1775,1759],{},[447,1777,1778,1781,1784,1787],{},[462,1779,1780],{},"Feedback nếu bị bỏ qua",[462,1782,1783],{},"Có (log)",[462,1785,1786],{},"Có (note in plan)",[462,1788,1789],{},"Có (warning)",[447,1791,1792,1795,1798,1800],{},[462,1793,1794],{},"Generate tự động",[462,1796,1797],{},"Có (PLAN_ADVICE)",[462,1799,1762],{},[462,1801,1762],{},[628,1803,1805],{"id":1804},"usecase-thực-tế","Usecase thực tế",[522,1807,1809],{"className":524,"code":1808,"language":526,"meta":527,"style":527},"-- Pin join order khi planner chọn sai trên dữ liệu skewed\nSET pg_plan_advice.advice = 'JOIN_ORDER(orders customers) NESTED_LOOP(customers)';\n\n-- Force hash join cho batch query nightly\nSET pg_plan_advice.advice = 'HASH_JOIN(events)';\n\n-- Theo dõi hint có được honor không\n-- Log: \"pg_plan_advice: hint 'SEQ_SCAN(o c)' not honored because index scan is cheaper\"\n",[529,1810,1811,1816,1821,1825,1830,1835,1839,1844],{"__ignoreMap":527},[532,1812,1813],{"class":534,"line":535},[532,1814,1815],{},"-- Pin join order khi planner chọn sai trên dữ liệu skewed\n",[532,1817,1818],{"class":534,"line":541},[532,1819,1820],{},"SET pg_plan_advice.advice = 'JOIN_ORDER(orders customers) NESTED_LOOP(customers)';\n",[532,1822,1823],{"class":534,"line":547},[532,1824,551],{"emptyLinePlaceholder":550},[532,1826,1827],{"class":534,"line":554},[532,1828,1829],{},"-- Force hash join cho batch query nightly\n",[532,1831,1832],{"class":534,"line":560},[532,1833,1834],{},"SET pg_plan_advice.advice = 'HASH_JOIN(events)';\n",[532,1836,1837],{"class":534,"line":566},[532,1838,551],{"emptyLinePlaceholder":550},[532,1840,1841],{"class":534,"line":572},[532,1842,1843],{},"-- Theo dõi hint có được honor không\n",[532,1845,1846],{"class":534,"line":578},[532,1847,1848],{},"-- Log: \"pg_plan_advice: hint 'SEQ_SCAN(o c)' not honored because index scan is cheaper\"\n",[681,1850,1851,1859],{"color":683,"icon":684},[432,1852,687,1853,691,1856],{},[436,1854,1855],{},"Câu PV — PG 19:",[693,1857,1858],{},"\"Postgres có query hint không? Khác gì Oracle?\"",[701,1860,1861],{},[432,1862,1863,1864,1866],{},"\"Postgres 19 có ",[529,1865,1651],{}," — hint nằm trong GUC setting thay vì SQL comment. Planner tự generate advice string từ plan nó chọn → đọc hiểu được. Lợi thế: SQL sạch, đổi hint không deploy, có feedback mechanism nếu hint bị planner bỏ qua. Oracle\u002FMySQL nhúng hint vào SQL comment → SQL bẩn, đổi hint phải deploy.\"",[427,1868,1870],{"id":1869},"_9-repack-online-table-rebuilding-postgres-19","9. REPACK — Online Table Rebuilding (Postgres 19)",[432,1872,1873,1874,1877,1878,1881,1882,1885],{},"REPACK gộp chức năng của ",[529,1875,1876],{},"VACUUM FULL"," (thu hồi disk space) và ",[529,1879,1880],{},"CLUSTER"," (sắp xếp lại row theo index) thành ",[436,1883,1884],{},"một lệnh duy nhất",", với chế độ CONCURRENTLY không lock bảng.",[522,1887,1889],{"className":524,"code":1888,"language":526,"meta":527,"style":527},"-- Reclaim space (thay VACUUM FULL)\nREPACK orders;\n\n-- Reorder theo index (thay CLUSTER)\nREPACK orders USING INDEX orders_created_at_idx;\n\n-- Online mode — chỉ lock ACCESS EXCLUSIVE vài ms lúc swap file cuối\nREPACK (CONCURRENTLY) orders USING INDEX orders_created_at_idx;\n",[529,1890,1891,1896,1901,1905,1910,1915,1919,1924],{"__ignoreMap":527},[532,1892,1893],{"class":534,"line":535},[532,1894,1895],{},"-- Reclaim space (thay VACUUM FULL)\n",[532,1897,1898],{"class":534,"line":541},[532,1899,1900],{},"REPACK orders;\n",[532,1902,1903],{"class":534,"line":547},[532,1904,551],{"emptyLinePlaceholder":550},[532,1906,1907],{"class":534,"line":554},[532,1908,1909],{},"-- Reorder theo index (thay CLUSTER)\n",[532,1911,1912],{"class":534,"line":560},[532,1913,1914],{},"REPACK orders USING INDEX orders_created_at_idx;\n",[532,1916,1917],{"class":534,"line":566},[532,1918,551],{"emptyLinePlaceholder":550},[532,1920,1921],{"class":534,"line":572},[532,1922,1923],{},"-- Online mode — chỉ lock ACCESS EXCLUSIVE vài ms lúc swap file cuối\n",[532,1925,1926],{"class":534,"line":578},[532,1927,1928],{},"REPACK (CONCURRENTLY) orders USING INDEX orders_created_at_idx;\n",[628,1930,1932],{"id":1931},"so-sánh-với-vacuum-full-cluster","So sánh với VACUUM FULL \u002F CLUSTER",[441,1934,1935,1951],{},[444,1936,1937],{},[447,1938,1939,1941,1943,1945,1948],{},[450,1940],{},[450,1942,1876],{},[450,1944,1880],{},[450,1946,1947],{},"REPACK",[450,1949,1950],{},"REPACK CONCURRENTLY",[457,1952,1953,1966,1980,1995],{},[447,1954,1955,1958,1960,1962,1964],{},[462,1956,1957],{},"Reclaim space",[462,1959,1759],{},[462,1961,1762],{},[462,1963,1759],{},[462,1965,1759],{},[447,1967,1968,1971,1973,1975,1978],{},[462,1969,1970],{},"Reorder row",[462,1972,1762],{},[462,1974,1759],{},[462,1976,1977],{},"Có (USING INDEX)",[462,1979,1977],{},[447,1981,1982,1985,1988,1990,1992],{},[462,1983,1984],{},"Lock bảng",[462,1986,1987],{},"ACCESS EXCLUSIVE (suốt)",[462,1989,1987],{},[462,1991,1987],{},[462,1993,1994],{},"ACCESS EXCLUSIVE (vài ms cuối)",[447,1996,1997,2000,2002,2004,2006],{},[462,1998,1999],{},"Đọc\u002Fghi trong lúc chạy",[462,2001,1762],{},[462,2003,1762],{},[462,2005,1762],{},[462,2007,1759],{},[628,2009,2011],{"id":2010},"cơ-chế-concurrently","Cơ chế CONCURRENTLY",[2013,2014,2015,2018,2021,2024],"ol",{},[1113,2016,2017],{},"Tạo bảng mới, copy row theo thứ tự index.",[1113,2019,2020],{},"Trigger ghi log vào queue mọi thay đổi trên bảng cũ trong lúc copy.",[1113,2022,2023],{},"Khi copy xong, apply queue (replay thay đổi).",[1113,2025,2026],{},"Swap file — ACCESS EXCLUSIVE lock chỉ vài ms.",[681,2028,2029,2036],{"color":683,"icon":684},[432,2030,687,2031,691,2033],{},[436,2032,1855],{},[693,2034,2035],{},"\"Làm sao defragment bảng 500GB mà không downtime?\"",[701,2037,2038],{},[432,2039,1146,2040,2043,2044,2047],{},[529,2041,2042],{},"REPACK (CONCURRENTLY)"," — PG 19 gộp VACUUM FULL + CLUSTER. Bảng vẫn đọc\u002Fghi được trong suốt quá trình. Chỉ lock ACCESS EXCLUSIVE vài ms lúc swap file cuối. Trước PG 19: ",[529,2045,2046],{},"pg_repack"," extension; PG 19: built-in.\"",[427,2049,2051],{"id":2050},"_10-query-optimization-checklist","10. Query optimization checklist",[681,2053,2055],{"color":2054,"icon":383},"success",[2013,2056,2057,2060,2063,2070,2073,2080,2083,2086,2093,2096,2103,2109,2120,2127,2134],{},[1113,2058,2059],{},"✅ EXPLAIN ANALYZE để xem plan thật.",[1113,2061,2062],{},"✅ Tránh Seq Scan trên bảng lớn — check index.",[1113,2064,2065,2066,2069],{},"✅ Statistics fresh — ",[529,2067,2068],{},"ANALYZE"," định kỳ (auto-vacuum lo, nhưng manual khi bulk load).",[1113,2071,2072],{},"✅ JOIN cùng kiểu dữ liệu — tránh implicit cast.",[1113,2074,2075,2076,2079],{},"✅ Pagination dùng keyset (",[529,2077,2078],{},"WHERE id > last_id",") cho bảng cực lớn — OFFSET chậm khi lệch sâu.",[1113,2081,2082],{},"✅ Composite index theo left-most prefix.",[1113,2084,2085],{},"✅ Partial index nếu filter cố định.",[1113,2087,2088,2089,2092],{},"✅ ",[529,2090,2091],{},"LIMIT"," để dừng sớm.",[1113,2094,2095],{},"✅ Connection pool (PgBouncer) cho production.",[1113,2097,2098,2099,2102],{},"✅ Postgres 18\u002F19 — bật AIO config (",[529,2100,2101],{},"io_method = io_uring"," trên Linux).",[1113,2104,2105,2106,2108],{},"✅ PG 19 — dùng ",[529,2107,1651],{}," để lock plan khi cần ổn định performance.",[1113,2110,2105,2111,2113,2114,2116,2117,2119],{},[529,2112,1950],{}," thay ",[529,2115,1876],{}," hoặc ",[529,2118,1880],{}," để tránh lock bảng.",[1113,2121,2122,2123,2126],{},"✅ PG 19 — ",[529,2124,2125],{},"autovacuum_max_parallel_workers > 0"," cho bảng nhiều index.",[1113,2128,2129,2130,2133],{},"✅ PG 19 — enable ",[529,2131,2132],{},"data_checksums"," online cho production.",[1113,2135,2122,2136,2113,2139,2141],{},[529,2137,2138],{},"COPY TO FORMAT JSON",[529,2140,1052],{}," khi export bảng lớn.",[427,2143,2145],{"id":2144},"_11-performance-tuning-configuration","11. Performance tuning configuration",[628,2147,2149],{"id":2148},"tham-số-quan-trọng-postgresqlconf","Tham số quan trọng (postgresql.conf)",[522,2151,2154],{"className":2152,"code":2153,"language":1614},[1612],"# Memory\nshared_buffers = 25% RAM            # cache buffer\neffective_cache_size = 75% RAM      # hint planner\nwork_mem = 32MB                     # mỗi sort\u002Fhash op\nmaintenance_work_mem = 512MB        # VACUUM, CREATE INDEX\n\n# Checkpoint\ncheckpoint_timeout = 10min\nmax_wal_size = 4GB\n\n# Postgres 18\u002F19 — AIO\nio_method = io_uring                # Linux 5.10+ only\nio_max_concurrency = 256\n\n# Logging\nlog_min_duration_statement = 1000ms  # log query > 1s\n\n# Autovacuum — PG 19 parallel\nautovacuum_max_parallel_workers = 4\n",[529,2155,2153],{"__ignoreMap":527},[628,2157,2159],{"id":2158},"parallel-autovacuum-postgres-19","Parallel Autovacuum — Postgres 19",[432,2161,2162,2163,2166],{},"Postgres 19 cho phép autovacuum chạy ",[436,2164,2165],{},"song song nhiều worker"," để vacuum index:",[522,2168,2170],{"className":524,"code":2169,"language":526,"meta":527,"style":527},"-- Cluster-wide default\nALTER SYSTEM SET autovacuum_max_parallel_workers = 4;\n\n-- Per-table override (ưu tiên hơn)\nALTER TABLE events SET (autovacuum_parallel_workers = 6);\n",[529,2171,2172,2177,2182,2186,2191],{"__ignoreMap":527},[532,2173,2174],{"class":534,"line":535},[532,2175,2176],{},"-- Cluster-wide default\n",[532,2178,2179],{"class":534,"line":541},[532,2180,2181],{},"ALTER SYSTEM SET autovacuum_max_parallel_workers = 4;\n",[532,2183,2184],{"class":534,"line":547},[532,2185,551],{"emptyLinePlaceholder":550},[532,2187,2188],{"class":534,"line":554},[532,2189,2190],{},"-- Per-table override (ưu tiên hơn)\n",[532,2192,2193],{"class":534,"line":560},[532,2194,2195],{},"ALTER TABLE events SET (autovacuum_parallel_workers = 6);\n",[1110,2197,2198,2205,2215,2221],{},[1113,2199,2200,2201,2204],{},"Mỗi worker xử lý ",[436,2202,2203],{},"một index"," — bảng nhiều index vacuum nhanh hơn rất nhiều.",[1113,2206,2207,2210,2211,2214],{},[436,2208,2209],{},"Disabled by default"," (",[529,2212,2213],{},"autovacuum_max_parallel_workers = 0",").",[1113,2216,2217,2220],{},[529,2218,2219],{},"autovacuum_parallel_workers"," là per-table storage parameter.",[1113,2222,2223],{},"Đặc biệt hiệu quả trên bảng heavily-indexed (10+ index) — thời gian vacuum giảm tuyến tính theo số worker.",[681,2225,2226,2233],{"color":683,"icon":684},[432,2227,687,2228,691,2230],{},[436,2229,1138],{},[693,2231,2232],{},"\"Làm sao tăng tốc VACUUM trên bảng có 20 index?\"",[701,2234,2235],{},[432,2236,2237,2238,2241,2242,2245],{},"\"Postgres 19 hỗ trợ parallel autovacuum. Set ",[529,2239,2240],{},"autovacuum_parallel_workers = 4"," (hoặc 6) trên bảng đó — mỗi worker vacuum một index song song. Kết hợp với ",[529,2243,2244],{},"maintenance_work_mem"," đủ lớn.\"",[628,2247,2249],{"id":2248},"online-data-checksums-postgres-19","Online Data Checksums — Postgres 19",[432,2251,2252,2253,2256,2257,2260],{},"Checksum giúp phát hiện data corruption ở storage level. ",[436,2254,2255],{},"Trước PG 19",": bắt buộc initdb với ",[529,2258,2259],{},"--data-checksums"," hoặc shutdown cluster để enable → không thay đổi được trên running system.",[432,2262,2263,2264,2267],{},"PG 19 cho phép enable\u002Fdisable checksum ",[436,2265,2266],{},"online",", không cần restart:",[522,2269,2271],{"className":524,"code":2270,"language":526,"meta":527,"style":527},"-- Enable checksum với rate limit (không ảnh hưởng production)\nSELECT pg_enable_data_checksums(cost_delay := 10, cost_limit := 1000);\n\n-- Theo dõi tiến trình\nSHOW data_checksums;\n-- Giá trị: 'off' → 'inprogress-on' → 'on'\n\n-- Disable nếu cần (cẩn thận!)\n-- SELECT pg_disable_data_checksums();\n",[529,2272,2273,2278,2283,2287,2292,2297,2302,2306,2311],{"__ignoreMap":527},[532,2274,2275],{"class":534,"line":535},[532,2276,2277],{},"-- Enable checksum với rate limit (không ảnh hưởng production)\n",[532,2279,2280],{"class":534,"line":541},[532,2281,2282],{},"SELECT pg_enable_data_checksums(cost_delay := 10, cost_limit := 1000);\n",[532,2284,2285],{"class":534,"line":547},[532,2286,551],{"emptyLinePlaceholder":550},[532,2288,2289],{"class":534,"line":554},[532,2290,2291],{},"-- Theo dõi tiến trình\n",[532,2293,2294],{"class":534,"line":560},[532,2295,2296],{},"SHOW data_checksums;\n",[532,2298,2299],{"class":534,"line":566},[532,2300,2301],{},"-- Giá trị: 'off' → 'inprogress-on' → 'on'\n",[532,2303,2304],{"class":534,"line":572},[532,2305,551],{"emptyLinePlaceholder":550},[532,2307,2308],{"class":534,"line":578},[532,2309,2310],{},"-- Disable nếu cần (cẩn thận!)\n",[532,2312,2313],{"class":534,"line":583},[532,2314,2315],{},"-- SELECT pg_disable_data_checksums();\n",[1110,2317,2318,2328,2331],{},[1113,2319,2320,2323,2324,2327],{},[529,2321,2322],{},"cost_delay"," \u002F ",[529,2325,2326],{},"cost_limit",": throttle giống VACUUM — không làm quá tải I\u002FO.",[1113,2329,2330],{},"Tiến trình chạy background, có thể pause\u002Fresume.",[1113,2332,2333],{},"Có thể disable ngược lại nếu cần performance tuyệt đối.",[681,2335,687,2336,2339],{"color":766,"icon":684},[436,2337,2338],{},"Production best practice PG 19:"," Luôn enable data checksums trên production. Với PG 19, có thể enable online — không còn lý do để skip.",[628,2341,2343],{"id":2342},"connection-pooling","Connection pooling",[432,2345,2346,2347,2350],{},"Postgres mỗi connection = 1 OS process (~10MB RAM). Production ",[436,2348,2349],{},"bắt buộc"," dùng pooler:",[1110,2352,2353,2359,2365],{},[1113,2354,2355,2358],{},[436,2356,2357],{},"PgBouncer"," — phổ biến nhất, transaction-level pooling.",[1113,2360,2361,2364],{},[436,2362,2363],{},"Pgpool-II"," — feature đầy đủ hơn.",[1113,2366,2367,2370],{},[436,2368,2369],{},"Supavisor"," (Supabase) — pgbouncer compatible.",[427,2372,2374],{"id":2373},"_12-replication-ha","12. Replication & HA",[441,2376,2377,2386],{},[444,2378,2379],{},[447,2380,2381,2383],{},[450,2382,452],{},[450,2384,2385],{},"Mô tả",[457,2387,2388,2398,2408],{},[447,2389,2390,2395],{},[462,2391,2392],{},[436,2393,2394],{},"Streaming replication",[462,2396,2397],{},"Async\u002Fsync, byte-level WAL stream tới replica",[447,2399,2400,2405],{},[462,2401,2402],{},[436,2403,2404],{},"Logical replication",[462,2406,2407],{},"Theo bảng\u002Frow, dùng cho cross-version, partial sync",[447,2409,2410,2415],{},[462,2411,2412],{},[436,2413,2414],{},"Synchronous commit",[462,2416,2417],{},"Master chờ replica confirm trước khi return",[628,2419,2421],{"id":2420},"logical-replication-cải-tiến-pg-19","Logical replication — cải tiến PG 19",[522,2423,2425],{"className":524,"code":2424,"language":526,"meta":527,"style":527},"-- Sequence synchronization: replicate sequence values cùng table\nCREATE PUBLICATION my_pub FOR ALL TABLES, ALL SEQUENCES;\n\n-- EXCEPT TABLE: loại trừ bảng không muốn replicate\nCREATE PUBLICATION prod_pub FOR ALL TABLES\n    EXCEPT (TABLE audit_log, temp_imports);\n\n-- Filter row trong publication (PG 15+ có WHERE clause)\nCREATE PUBLICATION us_customers FOR TABLE customers\n    WHERE (country = 'US');\n",[529,2426,2427,2432,2437,2441,2446,2451,2456,2460,2465,2470],{"__ignoreMap":527},[532,2428,2429],{"class":534,"line":535},[532,2430,2431],{},"-- Sequence synchronization: replicate sequence values cùng table\n",[532,2433,2434],{"class":534,"line":541},[532,2435,2436],{},"CREATE PUBLICATION my_pub FOR ALL TABLES, ALL SEQUENCES;\n",[532,2438,2439],{"class":534,"line":547},[532,2440,551],{"emptyLinePlaceholder":550},[532,2442,2443],{"class":534,"line":554},[532,2444,2445],{},"-- EXCEPT TABLE: loại trừ bảng không muốn replicate\n",[532,2447,2448],{"class":534,"line":560},[532,2449,2450],{},"CREATE PUBLICATION prod_pub FOR ALL TABLES\n",[532,2452,2453],{"class":534,"line":566},[532,2454,2455],{},"    EXCEPT (TABLE audit_log, temp_imports);\n",[532,2457,2458],{"class":534,"line":572},[532,2459,551],{"emptyLinePlaceholder":550},[532,2461,2462],{"class":534,"line":578},[532,2463,2464],{},"-- Filter row trong publication (PG 15+ có WHERE clause)\n",[532,2466,2467],{"class":534,"line":583},[532,2468,2469],{},"CREATE PUBLICATION us_customers FOR TABLE customers\n",[532,2471,2472],{"class":534,"line":589},[532,2473,2474],{},"    WHERE (country = 'US');\n",[432,2476,2477,691,2480,2483,2484,2487],{},[436,2478,2479],{},"Dynamic WAL level (PG 19):",[529,2481,2482],{},"effective_wal_level"," tự động tăng lên ",[529,2485,2486],{},"logical"," khi cần, không cần restart — giảm rủi ro quên set WAL level cho logical replication.",[681,2489,2490,2495],{"color":766,"icon":684},[432,2491,687,2492],{},[436,2493,2494],{},"So sánh logical replication PG 19:",[1110,2496,2497,2503,2509],{},[1113,2498,2499,2502],{},[529,2500,2501],{},"FOR ALL TABLES, ALL SEQUENCES"," — lần đầu tiên replicate sequence value, critical khi failover.",[1113,2504,2505,2508],{},[529,2506,2507],{},"EXCEPT"," clause — không cần liệt kê từng bảng muốn replicate, chỉ exclude những bảng không muốn.",[1113,2510,2511],{},"Dynamic WAL level — tránh quên config, tự động nâng cấp khi tạo publication.",[427,2513,2515],{"id":2514},"_13-postgres-đặc-thù-khác-sql-server-mysql","13. Postgres đặc thù — khác SQL Server \u002F MySQL",[441,2517,2518,2531],{},[444,2519,2520],{},[447,2521,2522,2524,2527,2529],{},[450,2523],{},[450,2525,2526],{},"Postgres",[450,2528,168],{},[450,2530,223],{},[457,2532,2533,2554,2568,2588,2599,2622,2643,2666,2685,2705,2718],{},[447,2534,2535,2538,2543,2548],{},[462,2536,2537],{},"Identifier",[462,2539,2540],{},[529,2541,2542],{},"\"Name\"",[462,2544,2545],{},[529,2546,2547],{},"[Name]",[462,2549,2550,2551],{},"backtick ",[529,2552,2553],{},"`Name`",[447,2555,2556,2559,2562,2565],{},[462,2557,2558],{},"Case sensitive",[462,2560,2561],{},"identifier yes nếu quote",[462,2563,2564],{},"no",[462,2566,2567],{},"tuỳ table_name_case",[447,2569,2570,2573,2579,2584],{},[462,2571,2572],{},"String",[462,2574,2575,2578],{},[529,2576,2577],{},"'text'"," (UTF-8)",[462,2580,2581],{},[529,2582,2583],{},"N'text'",[462,2585,2586],{},[529,2587,2577],{},[447,2589,2590,2593,2595,2597],{},[462,2591,2592],{},"Concat",[462,2594,950],{},[462,2596],{},[462,2598,950],{},[447,2600,2601,2604,2612,2617],{},[462,2602,2603],{},"Auto-increment",[462,2605,2606,2323,2609],{},[529,2607,2608],{},"GENERATED AS IDENTITY",[529,2610,2611],{},"SERIAL",[462,2613,2614],{},[529,2615,2616],{},"IDENTITY",[462,2618,2619],{},[529,2620,2621],{},"AUTO_INCREMENT",[447,2623,2624,2627,2633,2638],{},[462,2625,2626],{},"Boolean",[462,2628,2629,2632],{},[529,2630,2631],{},"BOOLEAN"," thật",[462,2634,2635],{},[529,2636,2637],{},"BIT 0\u002F1",[462,2639,2640],{},[529,2641,2642],{},"TINYINT(1) 0\u002F1",[447,2644,2645,2648,2657,2662],{},[462,2646,2647],{},"Now",[462,2649,2650,2653,2654],{},[529,2651,2652],{},"NOW()",", ",[529,2655,2656],{},"CURRENT_TIMESTAMP",[462,2658,2659],{},[529,2660,2661],{},"SYSUTCDATETIME()",[462,2663,2664],{},[529,2665,2652],{},[447,2667,2668,2671,2676,2681],{},[462,2669,2670],{},"Limit",[462,2672,2673],{},[529,2674,2675],{},"LIMIT n OFFSET m",[462,2677,2678],{},[529,2679,2680],{},"OFFSET .. FETCH",[462,2682,2683],{},[529,2684,2675],{},[447,2686,2687,2690,2695,2700],{},[462,2688,2689],{},"UPSERT",[462,2691,2692],{},[529,2693,2694],{},"ON CONFLICT DO UPDATE",[462,2696,2697],{},[529,2698,2699],{},"MERGE",[462,2701,2702],{},[529,2703,2704],{},"ON DUPLICATE KEY UPDATE",[447,2706,2707,2710,2713,2715],{},[462,2708,2709],{},"Schema vs DB",[462,2711,2712],{},"DB chứa nhiều schema",[462,2714,2712],{},[462,2716,2717],{},"DB = schema",[447,2719,2720,2723,2726,2729],{},[462,2721,2722],{},"Concurrency",[462,2724,2725],{},"MVCC native",[462,2727,2728],{},"Lock-based default",[462,2730,2731],{},"InnoDB MVCC",[681,2733,2735,2736],{"color":766,"icon":2734},"i-lucide-arrow-right","Tiếp theo: ",[755,2737,2738],{"href":216},"Câu hỏi phỏng vấn PostgreSQL",[2740,2741,2742],"style",{},"html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":527,"searchDepth":541,"depth":541,"links":2744},[2745,2751,2757,2758,2759,2763,2764,2767,2772,2776,2777,2783,2786],{"id":429,"depth":541,"text":430,"children":2746},[2747,2748,2749,2750],{"id":630,"depth":547,"text":631},{"id":649,"depth":547,"text":650},{"id":712,"depth":547,"text":713},{"id":785,"depth":547,"text":786},{"id":807,"depth":541,"text":808,"children":2752},[2753,2754,2755,2756],{"id":811,"depth":547,"text":812},{"id":863,"depth":547,"text":864},{"id":980,"depth":547,"text":981},{"id":1041,"depth":547,"text":1042},{"id":1160,"depth":541,"text":1161},{"id":1261,"depth":541,"text":1262},{"id":1321,"depth":541,"text":1322,"children":2760},[2761,2762],{"id":1370,"depth":547,"text":1371},{"id":1418,"depth":547,"text":1419},{"id":1508,"depth":541,"text":1509},{"id":1579,"depth":541,"text":1580,"children":2765},[2766],{"id":1622,"depth":547,"text":1623},{"id":1640,"depth":541,"text":1641,"children":2768},[2769,2770,2771],{"id":1694,"depth":547,"text":1695},{"id":1713,"depth":547,"text":1714},{"id":1804,"depth":547,"text":1805},{"id":1869,"depth":541,"text":1870,"children":2773},[2774,2775],{"id":1931,"depth":547,"text":1932},{"id":2010,"depth":547,"text":2011},{"id":2050,"depth":541,"text":2051},{"id":2144,"depth":541,"text":2145,"children":2778},[2779,2780,2781,2782],{"id":2148,"depth":547,"text":2149},{"id":2158,"depth":547,"text":2159},{"id":2248,"depth":547,"text":2249},{"id":2342,"depth":547,"text":2343},{"id":2373,"depth":541,"text":2374,"children":2784},[2785],{"id":2420,"depth":547,"text":2421},{"id":2514,"depth":541,"text":2515},"Feature riêng Postgres — JSONB, array, range, extension (pgvector, PostGIS, pg_trgm), partial\u002Fexpression index, performance tuning.","md",null,{},{"title":188,"icon":191},{"title":422,"description":2787},"p3RbM-d_rhCSjO5L_7xVksNoBAnaVvgdYzvXRev4kbM",[2795,2797],{"title":183,"path":210,"stem":211,"description":2796,"icon":186,"children":-1},"JOIN, LATERAL, CTE recursive, window function, MVCC, transaction, isolation, EXPLAIN — gốc Postgres.",{"title":193,"path":216,"stem":217,"description":2798,"icon":196,"children":-1},"70+ câu hỏi phỏng vấn Postgres cho dev backend \u002F fullstack — đáp án ngắn, có dẫn chiếu Postgres 18 & 19.",1783490365692]