[{"data":1,"prerenderedAt":2544},["ShallowReactive",2],{"navigation_docs":3,"-tu-hoc-database-postgresql-cau-hoi-phong-van":420,"-tu-hoc-database-postgresql-cau-hoi-phong-van-surround":2539},[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":2532,"extension":2533,"links":2534,"meta":2535,"navigation":2536,"path":216,"seo":2537,"stem":217,"__hash__":2538},"docs\u002F2.tu-hoc\u002F1.database\u002F3.postgresql\u002F5.cau-hoi-phong-van.md","Câu hỏi phỏng vấn PostgreSQL",{"type":424,"value":425,"toc":2432},"minimark",[426,431,436,483,487,493,542,547,635,639,642,646,650,663,667,681,688,692,708,711,715,721,725,743,746,750,753,757,781,785,789,804,808,827,831,838,842,845,861,865,881,885,888,916,920,924,934,938,941,945,956,971,984,988,995,1010,1014,1019,1034,1038,1042,1045,1049,1052,1067,1071,1077,1086,1090,1093,1107,1111,1115,1118,1122,1125,1129,1132,1136,1139,1148,1152,1155,1164,1168,1171,1175,1178,1182,1186,1192,1196,1199,1203,1209,1213,1216,1220,1223,1227,1230,1234,1237,1241,1247,1251,1255,1269,1281,1293,1297,1307,1311,1321,1325,1329,1332,1336,1350,1354,1357,1361,1367,1371,1375,1389,1393,1407,1411,1429,1433,1436,1440,1443,1460,1464,1468,1482,1486,1494,1498,1506,1512,1516,1533,1537,1540,1554,1558,1565,1569,1572,1576,1580,1586,1597,1651,1654,1658,1665,1679,1688,1703,1706,1721,1732,1736,1745,1818,1829,1848,1851,1855,1864,1911,1918,1924,1928,1937,1964,1989,1992,2002,2006,2014,2057,2060,2075,2081,2085,2094,2102,2111,2114,2128,2191,2195,2202,2209,2217,2220,2231,2245,2249,2256,2271,2274,2307,2332,2342,2346,2349,2363,2370,2375,2400,2402,2416,2420,2428],[427,428,430],"h2",{"id":429},"a-tổng-quan-lịch-sử","A. Tổng quan & lịch sử",[432,433,435],"h3",{"id":434},"_1-postgres-khác-mysql-ở-điểm-nào","1. Postgres khác MySQL ở điểm nào?",[437,438,439,447,453,459,465,471,477],"ul",{},[440,441,442,446],"li",{},[443,444,445],"strong",{},"MVCC native",", không có Read Uncommitted thực sự (dirty read).",[440,448,449,452],{},[443,450,451],{},"Extension"," mạnh (PostGIS, pgvector, pg_trgm…).",[440,454,455,458],{},[443,456,457],{},"JSONB"," chuẩn, có GIN index.",[440,460,461,464],{},[443,462,463],{},"Array, range type"," native.",[440,466,467,470],{},[443,468,469],{},"CHECK constraint"," thực sự enforce (MySQL 8 mới có).",[440,472,473,476],{},[443,474,475],{},"Procedural language"," đa dạng (PL\u002FpgSQL, PL\u002FPython, PL\u002FPerl).",[440,478,479,482],{},[443,480,481],{},"Standard SQL compliance"," cao hơn.",[432,484,486],{"id":485},"_2-có-gì-mới-đáng-chú-ý-ở-postgres-18-19","2. Có gì mới đáng chú ý ở Postgres 18 & 19?",[488,489,490],"p",{},[443,491,492],{},"Postgres 18 (09\u002F2025):",[437,494,495,501,507,513,519,525,530,536],{},[440,496,497,500],{},[443,498,499],{},"Async I\u002FO subsystem"," — đọc storage nhanh ~3×.",[440,502,503,506],{},[443,504,505],{},"uuidv7()"," built-in.",[440,508,509,512],{},[443,510,511],{},"Virtual generated columns"," mặc định.",[440,514,515,518],{},[443,516,517],{},"OLD\u002FNEW"," trong RETURNING của INSERT\u002FUPDATE\u002FDELETE\u002FMERGE.",[440,520,521,524],{},[443,522,523],{},"Skip scan"," cho multicolumn B-tree.",[440,526,527,464],{},[443,528,529],{},"OAuth authentication",[440,531,532,535],{},[443,533,534],{},"pg_upgrade"," giữ statistics.",[440,537,538,541],{},[443,539,540],{},"Temporal constraints"," (PK\u002FUK\u002FFK over ranges).",[488,543,544],{},[443,545,546],{},"Postgres 19 (09\u002F2026):",[437,548,549,555,561,567,573,597,603,617,623,629],{},[440,550,551,554],{},[443,552,553],{},"SQL\u002FPGQ Property Graph Queries"," — truy vấn đồ thị chuẩn SQL.",[440,556,557,560],{},[443,558,559],{},"ON CONFLICT DO SELECT"," — hành vi UPSERT không write khi row đã tồn tại.",[440,562,563,566],{},[443,564,565],{},"FOR PORTION OF"," — UPDATE\u002FDELETE trên dữ liệu temporal (khoảng thời gian).",[440,568,569,572],{},[443,570,571],{},"GROUP BY ALL"," — nhóm theo mọi cột SELECT không phải aggregate.",[440,574,575,578,579,583,584,583,587,583,590,583,593,596],{},[443,576,577],{},"IGNORE NULLS"," trong window function (",[580,581,582],"code",{},"LAG",", ",[580,585,586],{},"LEAD",[580,588,589],{},"FIRST_VALUE",[580,591,592],{},"LAST_VALUE",[580,594,595],{},"NTH_VALUE",").",[440,598,599,602],{},[443,600,601],{},"pg_plan_advice"," — plan hint cho planner không cần extension thứ 3.",[440,604,605,608,609,612,613,616],{},[443,606,607],{},"REPACK"," — ",[580,610,611],{},"REPACK TABLE CONCURRENTLY"," rebuild bảng không lock, thay thế nhẹ hơn ",[580,614,615],{},"VACUUM FULL",".",[440,618,619,622],{},[443,620,621],{},"Parallel Autovacuum"," — autovacuum chạy multi-worker song song trên cùng một bảng.",[440,624,625,628],{},[443,626,627],{},"JSON COPY TO"," — export JSON trực tiếp từ câu lệnh COPY.",[440,630,631,634],{},[443,632,633],{},"Online Data Checksums"," — bật checksum không cần shutdown cluster.",[432,636,638],{"id":637},"_3-postgres-version-release-cadence","3. Postgres version release cadence?",[488,640,641],{},"Mỗi tháng 9, support 5 năm. v18 release 25\u002F09\u002F2025, v19 release 09\u002F2026.",[427,643,645],{"id":644},"b-kiểu-dữ-liệu","B. Kiểu dữ liệu",[432,647,649],{"id":648},"_4-varchar-vs-text-trong-postgres","4. VARCHAR vs TEXT trong Postgres?",[488,651,652,655,656,659,660,616],{},[443,653,654],{},"Không khác về performance."," Cả 2 dùng cùng cách lưu, có TOAST. ",[580,657,658],{},"VARCHAR(n)"," chỉ thêm enforce length. Mặc định dùng ",[580,661,662],{},"TEXT",[432,664,666],{"id":665},"_5-timestamp-vs-timestamptz","5. TIMESTAMP vs TIMESTAMPTZ?",[437,668,669,675],{},[440,670,671,674],{},[580,672,673],{},"TIMESTAMP",": không timezone, lưu nguyên giá trị.",[440,676,677,680],{},[580,678,679],{},"TIMESTAMPTZ",": convert sang UTC khi insert, convert ngược về session timezone khi read.",[488,682,683],{},[443,684,685,686,616],{},"Best practice: luôn dùng ",[580,687,679],{},[432,689,691],{"id":690},"_6-json-vs-jsonb","6. JSON vs JSONB?",[437,693,694,700],{},[440,695,696,699],{},[580,697,698],{},"JSON",": text raw, giữ format, parse mỗi query.",[440,701,702,704,705,616],{},[580,703,457],{},": binary, nén, query nhanh, ",[443,706,707],{},"index GIN",[488,709,710],{},"Mặc định dùng JSONB trừ khi cần giữ raw.",[432,712,714],{"id":713},"_7-uuidv7-khác-uuidv4","7. uuidv7 khác uuidv4?",[488,716,717,718],{},"uuidv7 chứa timestamp ở đầu → sort theo thời gian. B-tree index không bị page split như random uuidv4. ",[443,719,720],{},"Khuyến nghị uuidv7 cho mọi project mới Postgres 18+.",[432,722,724],{"id":723},"_8-serial-vs-identity","8. SERIAL vs IDENTITY?",[437,726,727,737],{},[440,728,729,732,733,736],{},[580,730,731],{},"SERIAL","\u002F",[580,734,735],{},"BIGSERIAL",": legacy, tạo sequence + default.",[440,738,739,742],{},[580,740,741],{},"GENERATED AS IDENTITY",": chuẩn ANSI, kiểm soát tốt hơn.",[488,744,745],{},"Postgres 10+ recommend IDENTITY.",[432,747,749],{"id":748},"_9-array-khi-nào-nên-dùng","9. Array khi nào nên dùng?",[488,751,752],{},"Khi: phần tử ít (\u003C 100), không cần FK \u002F JOIN từng giá trị, atomic với row. Còn lại → bảng phụ.",[432,754,756],{"id":755},"_10-range-type-là-gì","10. Range type là gì?",[488,758,759,760,583,763,583,766,583,769,772,773,776,777,780],{},"Khoảng giá trị: ",[580,761,762],{},"INT4RANGE",[580,764,765],{},"NUMRANGE",[580,767,768],{},"TSRANGE",[580,770,771],{},"DATERANGE",". Hỗ trợ operator ",[580,774,775],{},"&&"," (overlap), ",[580,778,779],{},"@>"," (contains). Cực mạnh cho booking, reservation.",[427,782,784],{"id":783},"c-ddl-ràng-buộc","C. DDL & ràng buộc",[432,786,788],{"id":787},"_11-schema-trong-postgres-là-gì","11. Schema trong Postgres là gì?",[488,790,791,792,795,796,799,800,803],{},"Namespace bên trong database. Default ",[580,793,794],{},"public",". Truy cập: ",[580,797,798],{},"schema.table",". Set ",[580,801,802],{},"search_path"," để default.",[432,805,807],{"id":806},"_12-database-vs-schema-vs-cluster","12. Database vs Schema vs Cluster?",[437,809,810,816,821],{},[440,811,812,815],{},[443,813,814],{},"Cluster",": 1 instance Postgres.",[440,817,818,820],{},[443,819,162],{},": container độc lập, không JOIN cross-database trực tiếp.",[440,822,823,826],{},[443,824,825],{},"Schema",": namespace trong database.",[432,828,830],{"id":829},"_13-check-constraint","13. CHECK constraint?",[488,832,833,834,837],{},"Ràng buộc business rule: ",[580,835,836],{},"CHECK (price >= 0)",". Postgres support đầy đủ từ lâu.",[432,839,841],{"id":840},"_14-exclude-constraint","14. EXCLUDE constraint?",[488,843,844],{},"Đặc thù Postgres — ngăn 2 row có overlap theo predicate. Dùng cho booking không trùng giờ:",[846,847,852],"pre",{"className":848,"code":849,"language":850,"meta":851,"style":851},"language-sql shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","EXCLUDE USING GIST (room_id WITH =, valid_during WITH &&)\n","sql","",[580,853,854],{"__ignoreMap":851},[855,856,859],"span",{"class":857,"line":858},"line",1,[855,860,849],{},[432,862,864],{"id":863},"_15-generated-column","15. Generated column?",[846,866,868],{"className":848,"code":867,"language":850,"meta":851,"style":851},"GENERATED ALWAYS AS (price * 1.1) STORED   -- vật lý\nGENERATED ALWAYS AS (price * 1.1) VIRTUAL  -- tính khi đọc (Postgres 18 default)\n",[580,869,870,875],{"__ignoreMap":851},[855,871,872],{"class":857,"line":858},[855,873,874],{},"GENERATED ALWAYS AS (price * 1.1) STORED   -- vật lý\n",[855,876,878],{"class":857,"line":877},2,[855,879,880],{},"GENERATED ALWAYS AS (price * 1.1) VIRTUAL  -- tính khi đọc (Postgres 18 default)\n",[432,882,884],{"id":883},"_16-domain-là-gì","16. Domain là gì?",[488,886,887],{},"User-defined type với constraint:",[846,889,891],{"className":848,"code":890,"language":850,"meta":851,"style":851},"CREATE DOMAIN email AS TEXT\n    CHECK (VALUE ~ '^.+@.+\\..+$');\n\nCREATE TABLE users (email_addr email);   -- tự enforce regex\n",[580,892,893,898,903,910],{"__ignoreMap":851},[855,894,895],{"class":857,"line":858},[855,896,897],{},"CREATE DOMAIN email AS TEXT\n",[855,899,900],{"class":857,"line":877},[855,901,902],{},"    CHECK (VALUE ~ '^.+@.+\\..+$');\n",[855,904,906],{"class":857,"line":905},3,[855,907,909],{"emptyLinePlaceholder":908},true,"\n",[855,911,913],{"class":857,"line":912},4,[855,914,915],{},"CREATE TABLE users (email_addr email);   -- tự enforce regex\n",[427,917,919],{"id":918},"d-dml-upsert","D. DML & UPSERT",[432,921,923],{"id":922},"_17-postgres-upsert-làm-thế-nào","17. Postgres UPSERT làm thế nào?",[488,925,926,929,930,933],{},[580,927,928],{},"INSERT ... ON CONFLICT (key) DO UPDATE SET ...",". Dùng ",[580,931,932],{},"EXCLUDED.col"," để reference row đang insert.",[432,935,937],{"id":936},"_18-returning-làm-gì","18. RETURNING làm gì?",[488,939,940],{},"Trả về row insert\u002Fupdate\u002Fdelete trong cùng statement — get ID vừa insert, audit log.",[432,942,944],{"id":943},"_19-postgres-18-returning-có-gì-mới","19. Postgres 18 RETURNING có gì mới?",[488,946,947,948,951,952,955],{},"Có ",[580,949,950],{},"OLD"," và ",[580,953,954],{},"NEW"," reference:",[846,957,959],{"className":848,"code":958,"language":850,"meta":851,"style":851},"UPDATE users SET age=age+1 WHERE id=1\nRETURNING OLD.age, NEW.age;\n",[580,960,961,966],{"__ignoreMap":851},[855,962,963],{"class":857,"line":858},[855,964,965],{},"UPDATE users SET age=age+1 WHERE id=1\n",[855,967,968],{"class":857,"line":877},[855,969,970],{},"RETURNING OLD.age, NEW.age;\n",[972,973,976,977,979,980,983],"callout",{"color":974,"icon":975},"primary","i-lucide-info","Từ PG 19, ",[580,978,559],{}," là lựa chọn nhanh hơn ",[580,981,982],{},"DO UPDATE ... RETURNING"," khi bạn chỉ muốn đọc row đã tồn tại mà không cần ghi gì cả — xem thêm câu 62.",[432,985,987],{"id":986},"_20-update-từ-join-trong-postgres","20. UPDATE từ JOIN trong Postgres?",[488,989,990,991,994],{},"Dùng ",[580,992,993],{},"FROM",":",[846,996,998],{"className":848,"code":997,"language":850,"meta":851,"style":851},"UPDATE p SET cat_name = c.name\nFROM categories c WHERE c.id = p.cat_id;\n",[580,999,1000,1005],{"__ignoreMap":851},[855,1001,1002],{"class":857,"line":858},[855,1003,1004],{},"UPDATE p SET cat_name = c.name\n",[855,1006,1007],{"class":857,"line":877},[855,1008,1009],{},"FROM categories c WHERE c.id = p.cat_id;\n",[432,1011,1013],{"id":1012},"_21-delete-từ-join","21. DELETE từ JOIN?",[488,1015,990,1016,994],{},[580,1017,1018],{},"USING",[846,1020,1022],{"className":848,"code":1021,"language":850,"meta":851,"style":851},"DELETE FROM o USING users u\nWHERE u.id = o.user_id AND u.banned = true;\n",[580,1023,1024,1029],{"__ignoreMap":851},[855,1025,1026],{"class":857,"line":858},[855,1027,1028],{},"DELETE FROM o USING users u\n",[855,1030,1031],{"class":857,"line":877},[855,1032,1033],{},"WHERE u.id = o.user_id AND u.banned = true;\n",[427,1035,1037],{"id":1036},"e-join-query","E. JOIN & query",[432,1039,1041],{"id":1040},"_22-lateral-join-dùng-làm-gì","22. LATERAL JOIN dùng làm gì?",[488,1043,1044],{},"Cho phép subquery bên phải reference bảng bên trái. Giải bài \"top N per group\", parameterized correlated query.",[432,1046,1048],{"id":1047},"_23-distinct-on-là-gì","23. DISTINCT ON là gì?",[488,1050,1051],{},"Đặc thù Postgres, giải bài \"1 row per group\":",[846,1053,1055],{"className":848,"code":1054,"language":850,"meta":851,"style":851},"SELECT DISTINCT ON (user_id) *\nFROM orders ORDER BY user_id, created_at DESC;\n",[580,1056,1057,1062],{"__ignoreMap":851},[855,1058,1059],{"class":857,"line":858},[855,1060,1061],{},"SELECT DISTINCT ON (user_id) *\n",[855,1063,1064],{"class":857,"line":877},[855,1065,1066],{},"FROM orders ORDER BY user_id, created_at DESC;\n",[432,1068,1070],{"id":1069},"_24-filter-where-trong-aggregate","24. FILTER (WHERE ...) trong aggregate?",[488,1072,1073,1074,994],{},"Aggregate có điều kiện, gọn hơn ",[580,1075,1076],{},"SUM(CASE WHEN ...)",[846,1078,1080],{"className":848,"code":1079,"language":850,"meta":851,"style":851},"COUNT(*) FILTER (WHERE status='paid')\n",[580,1081,1082],{"__ignoreMap":851},[855,1083,1084],{"class":857,"line":858},[855,1085,1079],{},[432,1087,1089],{"id":1088},"_25-cte-inline-vs-materialized","25. CTE inline vs materialized?",[488,1091,1092],{},"Postgres 12+:",[437,1094,1095,1101],{},[440,1096,1097,1100],{},[580,1098,1099],{},"AS NOT MATERIALIZED",": inline, planner tối ưu xuyên CTE (default).",[440,1102,1103,1106],{},[580,1104,1105],{},"AS MATERIALIZED",": chạy CTE 1 lần, cache.",[427,1108,1110],{"id":1109},"f-index","F. Index",[432,1112,1114],{"id":1113},"_26-postgres-có-những-loại-index-nào","26. Postgres có những loại index nào?",[488,1116,1117],{},"B-tree (default), Hash, GIN, GiST, SP-GiST, BRIN. Mỗi loại tối ưu cho usecase khác nhau.",[432,1119,1121],{"id":1120},"_27-khi-nào-dùng-gin","27. Khi nào dùng GIN?",[488,1123,1124],{},"Multi-value indexing: JSONB, array, full-text search.",[432,1126,1128],{"id":1127},"_28-khi-nào-dùng-brin","28. Khi nào dùng BRIN?",[488,1130,1131],{},"Bảng cực lớn, data sắp xếp tự nhiên theo cột (log time-series). Index siêu nhỏ.",[432,1133,1135],{"id":1134},"_29-partial-index","29. Partial index?",[488,1137,1138],{},"Index chỉ subset row có filter. Nhỏ hơn, nhanh hơn cho query cùng filter:",[846,1140,1142],{"className":848,"code":1141,"language":850,"meta":851,"style":851},"CREATE INDEX ... WHERE status = 'active';\n",[580,1143,1144],{"__ignoreMap":851},[855,1145,1146],{"class":857,"line":858},[855,1147,1141],{},[432,1149,1151],{"id":1150},"_30-expression-index","30. Expression index?",[488,1153,1154],{},"Index trên expression — giải bài non-sargable:",[846,1156,1158],{"className":848,"code":1157,"language":850,"meta":851,"style":851},"CREATE INDEX ... ON users (LOWER(email));\n",[580,1159,1160],{"__ignoreMap":851},[855,1161,1162],{"class":857,"line":858},[855,1163,1157],{},[432,1165,1167],{"id":1166},"_31-concurrently-trong-create-index","31. CONCURRENTLY trong CREATE INDEX?",[488,1169,1170],{},"Tạo index không lock bảng — production-safe.",[432,1172,1174],{"id":1173},"_32-index-only-scan-là-gì","32. Index Only Scan là gì?",[488,1176,1177],{},"Khi index có đủ cột query cần (covering) — Postgres không cần lookup heap. Nhanh nhất.",[427,1179,1181],{"id":1180},"g-transaction-mvcc","G. Transaction & MVCC",[432,1183,1185],{"id":1184},"_33-mvcc-là-gì-postgres-dùng-ra-sao","33. MVCC là gì? Postgres dùng ra sao?",[488,1187,1188,1189],{},"Multi-Version Concurrency Control. UPDATE\u002FDELETE không xoá row ngay mà tạo version mới + đánh dấu cũ là dead. Mỗi transaction thấy snapshot tại thời điểm bắt đầu. ",[443,1190,1191],{},"Đọc không block ghi.",[432,1193,1195],{"id":1194},"_34-vacuum-làm-gì","34. VACUUM làm gì?",[488,1197,1198],{},"Reclaim space từ row dead (do MVCC). Auto-vacuum chạy nền. VACUUM FULL rebuild bảng (lock dài).",[432,1200,1202],{"id":1201},"_35-default-isolation-của-postgres","35. Default isolation của Postgres?",[488,1204,1205,1208],{},[443,1206,1207],{},"Read Committed"," (nhưng dựa MVCC, không block ghi như SQL Server).",[432,1210,1212],{"id":1211},"_36-postgres-read-uncommitted-khác-gì-sql-server","36. Postgres Read Uncommitted khác gì SQL Server?",[488,1214,1215],{},"Postgres không có dirty read thực sự ngay cả ở Read Uncommitted — vẫn dùng MVCC snapshot. Khác SQL Server cho phép dirty read thực sự.",[432,1217,1219],{"id":1218},"_37-repeatable-read-trong-postgres","37. Repeatable Read trong Postgres?",[488,1221,1222],{},"Snapshot toàn transaction — không non-repeatable read, không phantom (mạnh hơn chuẩn ANSI).",[432,1224,1226],{"id":1225},"_38-serializable-trong-postgres","38. Serializable trong Postgres?",[488,1228,1229],{},"SSI (Serializable Snapshot Isolation) — optimistic, ít block hơn các DB khác. Nếu phát hiện conflict → abort 1 transaction.",[432,1231,1233],{"id":1232},"_39-wal-là-gì","39. WAL là gì?",[488,1235,1236],{},"Write-Ahead Log. Mọi thay đổi ghi vào WAL trước rồi mới ghi vào data file. Cho phép recovery sau crash, basis của replication.",[432,1238,1240],{"id":1239},"_40-pg_hbaconf","40. pg_hba.conf?",[488,1242,1243,1244,616],{},"File config authentication. Quy định \"ai từ đâu được vào DB nào với method gì\". Format: ",[580,1245,1246],{},"TYPE DATABASE USER ADDRESS METHOD",[427,1248,1250],{"id":1249},"h-json-array","H. JSON \u002F Array",[432,1252,1254],{"id":1253},"_41-jsonb-index-nào-hiệu-quả","41. JSONB index nào hiệu quả?",[488,1256,1257,1258,1261,1262,1264,1265,1268],{},"GIN với ",[580,1259,1260],{},"jsonb_path_ops"," cho operator ",[580,1263,779],{}," (containment). Hoặc B-tree trên ",[580,1266,1267],{},"(payload->>'key')"," cho lookup key cụ thể.",[432,1270,1272,1273,1276,1277,1280],{"id":1271},"_42-json-operator-vs","42. JSON operator ",[580,1274,1275],{},"->"," vs ",[580,1278,1279],{},"->>","?",[437,1282,1283,1288],{},[440,1284,1285,1287],{},[580,1286,1275],{},": trả JSONB.",[440,1289,1290,1292],{},[580,1291,1279],{},": trả TEXT (đã unwrap).",[432,1294,1296],{"id":1295},"_43-tìm-row-có-json-chứa-key","43. Tìm row có JSON chứa key?",[488,1298,1299,1302,1303,1306],{},[580,1300,1301],{},"WHERE payload ? 'key'"," (key tồn tại). ",[580,1304,1305],{},"WHERE payload @> '{\"key\": \"value\"}'"," (containment).",[432,1308,1310],{"id":1309},"_44-array-kiểm-tra-phần-tử","44. Array — kiểm tra phần tử?",[488,1312,1313,1316,1317,1320],{},[580,1314,1315],{},"WHERE 'vue' = ANY(tags)"," hoặc ",[580,1318,1319],{},"WHERE tags @> ARRAY['vue']",". GIN index trên tags để fast.",[427,1322,1324],{"id":1323},"i-extension","I. Extension",[432,1326,1328],{"id":1327},"_45-pgvector-dùng-làm-gì","45. pgvector dùng làm gì?",[488,1330,1331],{},"Lưu embedding (OpenAI, sentence-transformers) → semantic search bằng cosine\u002FL2 distance. Vector DB built into Postgres.",[432,1333,1335],{"id":1334},"_46-pg_trgm-dùng-làm-gì","46. pg_trgm dùng làm gì?",[488,1337,1338,1339,1342,1343,1346,1347,616],{},"Fuzzy search, similarity. Tìm \"iPone\" ra \"iPhone\". Operator ",[580,1340,1341],{},"%",", function ",[580,1344,1345],{},"similarity()",". GIN index ",[580,1348,1349],{},"gin_trgm_ops",[432,1351,1353],{"id":1352},"_47-postgis","47. PostGIS?",[488,1355,1356],{},"GIS extension — geometry, geography, spatial query. Postgres + PostGIS gần như standard cho ứng dụng địa lý.",[432,1358,1360],{"id":1359},"_48-pg_stat_statements","48. pg_stat_statements?",[488,1362,1363,1364,616],{},"Theo dõi statement performance — top query slow, query gọi nhiều. Bật trong ",[580,1365,1366],{},"shared_preload_libraries",[427,1368,1370],{"id":1369},"j-performance","J. Performance",[432,1372,1374],{"id":1373},"_49-explain-vs-explain-analyze","49. EXPLAIN vs EXPLAIN ANALYZE?",[437,1376,1377,1383],{},[440,1378,1379,1382],{},[580,1380,1381],{},"EXPLAIN",": dự đoán plan, không chạy.",[440,1384,1385,1388],{},[580,1386,1387],{},"EXPLAIN ANALYZE",": chạy thật, đo time + row thực tế.",[432,1390,1392],{"id":1391},"_50-seq-scan-và-index-scan","50. Seq Scan và Index Scan?",[437,1394,1395,1398,1401,1404],{},[440,1396,1397],{},"Seq Scan: full table — OK cho bảng nhỏ, tệ cho bảng lớn.",[440,1399,1400],{},"Index Scan: dùng index seek.",[440,1402,1403],{},"Index Only Scan: dùng index + đủ cột (covering).",[440,1405,1406],{},"Bitmap Index Scan: tốt khi nhiều row match index.",[432,1408,1410],{"id":1409},"_51-postgres-slow-query-bạn-debug-thế-nào","51. Postgres slow query — bạn debug thế nào?",[1412,1413,1414,1417,1420,1423,1426],"ol",{},[440,1415,1416],{},"EXPLAIN ANALYZE.",[440,1418,1419],{},"Check Seq Scan trên bảng lớn — thiếu index?",[440,1421,1422],{},"Statistics fresh chưa — ANALYZE.",[440,1424,1425],{},"work_mem đủ chưa (sort spill to disk).",[440,1427,1428],{},"pg_stat_statements top query.",[432,1430,1432],{"id":1431},"_52-connection-pool-vì-sao-cần","52. Connection pool — vì sao cần?",[488,1434,1435],{},"Postgres mỗi connection là 1 OS process ~10MB. Web app 100 connection = 1GB RAM ngay. Pool (PgBouncer) chia sẻ connection vật lý cho nhiều client logic.",[432,1437,1439],{"id":1438},"_53-index-không-được-dùng-tại-sao","53. Index không được dùng — tại sao?",[488,1441,1442],{},"Có thể:",[437,1444,1445,1448,1451,1454,1457],{},[440,1446,1447],{},"Statistics outdated → ANALYZE.",[440,1449,1450],{},"WHERE non-sargable (function lên cột).",[440,1452,1453],{},"Selectivity thấp → planner chọn seq scan.",[440,1455,1456],{},"Type mismatch → implicit cast hủy index.",[440,1458,1459],{},"Bảng quá nhỏ.",[427,1461,1463],{"id":1462},"k-replication-ha","K. Replication & HA",[432,1465,1467],{"id":1466},"_54-streaming-replication-vs-logical-replication","54. Streaming replication vs Logical replication?",[437,1469,1470,1476],{},[440,1471,1472,1475],{},[443,1473,1474],{},"Streaming",": stream WAL byte-level → replica giống hệt master.",[440,1477,1478,1481],{},[443,1479,1480],{},"Logical",": theo bảng\u002Frow, cho phép cross-version, partial replication, dùng cho ETL.",[432,1483,1485],{"id":1484},"_55-synchronous-vs-asynchronous-commit","55. Synchronous vs Asynchronous commit?",[437,1487,1488,1491],{},[440,1489,1490],{},"Async (default): commit ngay khi WAL local, không chờ replica → fast nhưng có thể mất giao dịch nếu master chết.",[440,1492,1493],{},"Sync: chờ replica ack → an toàn, chậm hơn.",[427,1495,1497],{"id":1496},"l-trick-scenario","L. Trick & scenario",[432,1499,1501,1502,1505],{"id":1500},"_56-bảng-100m-row-query-where-loweremail-rất-chậm-fix","56. Bảng 100M row, query ",[580,1503,1504],{},"WHERE LOWER(email) = ?"," rất chậm. Fix?",[488,1507,1508,1509],{},"Tạo expression index: ",[580,1510,1511],{},"CREATE INDEX ... ON users (LOWER(email));",[432,1513,1515],{"id":1514},"_57-update-10-triệu-row-không-downtime","57. UPDATE 10 triệu row, không downtime?",[437,1517,1518,1521,1527,1530],{},[440,1519,1520],{},"Batch theo PK range (10K row\u002Fbatch).",[440,1522,1523,1526],{},[580,1524,1525],{},"SET work_mem"," cao tạm thời cho session.",[440,1528,1529],{},"Tránh long transaction (block VACUUM, bloat).",[440,1531,1532],{},"Sau khi xong: VACUUM ANALYZE.",[432,1534,1536],{"id":1535},"_58-bảng-bloat-nguyên-nhân-và-fix","58. Bảng bloat — nguyên nhân và fix?",[488,1538,1539],{},"Do MVCC: UPDATE\u002FDELETE để lại dead row. Auto-vacuum không kịp với heavy write. Fix:",[437,1541,1542,1545],{},[440,1543,1544],{},"Tune autovacuum (frequent hơn).",[440,1546,1547,1549,1550,1553],{},[580,1548,615],{}," (lock) hoặc ",[580,1551,1552],{},"pg_repack"," (online).",[432,1555,1557],{"id":1556},"_59-khi-nào-dùng-postgres-thay-vì-nosql-như-mongodb","59. Khi nào dùng Postgres thay vì NoSQL như MongoDB?",[488,1559,1560,1561,1564],{},"Khi cần ACID, FK, transaction phức tạp. Với JSONB, Postgres làm gần được mọi việc MongoDB làm, ",[443,1562,1563],{},"plus"," SQL relational. Khuyến nghị: thử Postgres trước.",[432,1566,1568],{"id":1567},"_60-postgres-có-giới-hạn-về-scale-không","60. Postgres có giới hạn về scale không?",[488,1570,1571],{},"Vertical scale rất tốt (đến hàng TB). Horizontal scale write cần sharding (Citus extension, hoặc app-level). Read scale qua read replica dễ.",[427,1573,1575],{"id":1574},"m-postgresql-19-tính-năng-mới","M. PostgreSQL 19 — tính năng mới",[432,1577,1579],{"id":1578},"_61-sqlpgq-property-graph-query-là-gì-khi-nào-dùng","61. SQL\u002FPGQ Property Graph Query là gì? Khi nào dùng?",[488,1581,1582,1583,616],{},"Đây là chuẩn SQL:2023 cho truy vấn đồ thị, được Postgres 19 hỗ trợ qua extension ",[580,1584,1585],{},"pgq",[488,1587,1588,1589,1592,1593,1596],{},"Graph query cho phép mô hình hoá dữ liệu dưới dạng ",[443,1590,1591],{},"đỉnh"," (vertex) và ",[443,1594,1595],{},"cạnh"," (edge), thay vì table-row. Dùng cho: social network, recommendation, fraud detection, supply chain.",[846,1598,1600],{"className":848,"code":1599,"language":850,"meta":851,"style":851},"CREATE PROPERTY GRAPH social_graph\n  VERTEX TABLES (users KEY (id), posts KEY (id))\n  EDGE TABLES (friends KEY (id) SOURCE user_id REFERENCES users(id)\n                            DESTINATION friend_id REFERENCES users(id));\n\nSELECT * FROM GRAPH_TABLE (social_graph\n  MATCH (u IS users)-[f IS friends]->(friend IS users)\n  WHERE u.name = 'Alice'\n  COLUMNS (friend.name));\n",[580,1601,1602,1607,1612,1617,1622,1627,1633,1639,1645],{"__ignoreMap":851},[855,1603,1604],{"class":857,"line":858},[855,1605,1606],{},"CREATE PROPERTY GRAPH social_graph\n",[855,1608,1609],{"class":857,"line":877},[855,1610,1611],{},"  VERTEX TABLES (users KEY (id), posts KEY (id))\n",[855,1613,1614],{"class":857,"line":905},[855,1615,1616],{},"  EDGE TABLES (friends KEY (id) SOURCE user_id REFERENCES users(id)\n",[855,1618,1619],{"class":857,"line":912},[855,1620,1621],{},"                            DESTINATION friend_id REFERENCES users(id));\n",[855,1623,1625],{"class":857,"line":1624},5,[855,1626,909],{"emptyLinePlaceholder":908},[855,1628,1630],{"class":857,"line":1629},6,[855,1631,1632],{},"SELECT * FROM GRAPH_TABLE (social_graph\n",[855,1634,1636],{"class":857,"line":1635},7,[855,1637,1638],{},"  MATCH (u IS users)-[f IS friends]->(friend IS users)\n",[855,1640,1642],{"class":857,"line":1641},8,[855,1643,1644],{},"  WHERE u.name = 'Alice'\n",[855,1646,1648],{"class":857,"line":1647},9,[855,1649,1650],{},"  COLUMNS (friend.name));\n",[488,1652,1653],{},"Khi nào dùng: Khi bài toán có quan hệ nhiều tầng (n-hop), recursive traversal hoặc path-finding — các thứ SQL JOIN truyền thống viết dài dòng và chậm.",[432,1655,1657],{"id":1656},"_62-on-conflict-do-select-khác-do-update-do-nothing-ra-sao","62. ON CONFLICT DO SELECT khác DO UPDATE \u002F DO NOTHING ra sao?",[488,1659,1660,1661,1664],{},"Trước PG 19, ",[580,1662,1663],{},"INSERT ... ON CONFLICT"," chỉ hỗ trợ:",[437,1666,1667,1673],{},[440,1668,1669,1672],{},[580,1670,1671],{},"DO NOTHING"," — bỏ qua nếu conflict.",[440,1674,1675,1678],{},[580,1676,1677],{},"DO UPDATE"," — ghi đè nếu conflict (dù giá trị không đổi).",[488,1680,1681,1684,1685,994],{},[580,1682,1683],{},"DO SELECT"," mới trong PG 19 cho phép ",[443,1686,1687],{},"trả về row đã tồn tại mà không cần write",[846,1689,1691],{"className":848,"code":1690,"language":850,"meta":851,"style":851},"INSERT INTO users (email, name) VALUES ('john@example.com', 'John')\nON CONFLICT (email) DO SELECT;\n",[580,1692,1693,1698],{"__ignoreMap":851},[855,1694,1695],{"class":857,"line":858},[855,1696,1697],{},"INSERT INTO users (email, name) VALUES ('john@example.com', 'John')\n",[855,1699,1700],{"class":857,"line":877},[855,1701,1702],{},"ON CONFLICT (email) DO SELECT;\n",[488,1704,1705],{},"Khác biệt chính:",[437,1707,1708,1715,1718],{},[440,1709,1710,1711,1714],{},"Không tạo dead tuple hay WAL record → ",[443,1712,1713],{},"nhanh hơn hẳn DO UPDATE"," khi row không thay đổi.",[440,1716,1717],{},"Trả về toàn bộ row conflict (bao gồm cả cột không nằm trong INSERT).",[440,1719,1720],{},"Lý tưởng cho pattern \"get or create\" (đọc nếu có, insert nếu chưa).",[972,1722,1724,1725,1728,1729,1731],{"color":1723,"icon":268},"warning","Nếu trước đây bạn dùng ",[580,1726,1727],{},"ON CONFLICT DO UPDATE SET id=EXCLUDED.id"," chỉ để lấy row về — hãy chuyển sang ",[580,1730,1683],{}," trong PG 19.",[432,1733,1735],{"id":1734},"_63-for-portion-of-dùng-để-làm-gì","63. FOR PORTION OF dùng để làm gì?",[488,1737,1738,1739,1742,1743,994],{},"PG 19 thêm hỗ trợ cập nhật dữ liệu ",[443,1740,1741],{},"temporal"," (theo khoảng thời gian) bằng ",[580,1744,565],{},[846,1746,1748],{"className":848,"code":1747,"language":850,"meta":851,"style":851},"CREATE TABLE policy (\n    id INT,\n    premium NUMERIC,\n    valid_from DATE,\n    valid_to DATE,\n    PERIOD FOR validity (valid_from, valid_to)\n);\n\n-- Chỉ update premium trong tháng 6\nUPDATE policy FOR PORTION OF validity\nFROM '2026-06-01' TO '2026-06-30'\nSET premium = premium * 1.1\nWHERE id = 100;\n",[580,1749,1750,1755,1760,1765,1770,1775,1780,1785,1789,1794,1800,1806,1812],{"__ignoreMap":851},[855,1751,1752],{"class":857,"line":858},[855,1753,1754],{},"CREATE TABLE policy (\n",[855,1756,1757],{"class":857,"line":877},[855,1758,1759],{},"    id INT,\n",[855,1761,1762],{"class":857,"line":905},[855,1763,1764],{},"    premium NUMERIC,\n",[855,1766,1767],{"class":857,"line":912},[855,1768,1769],{},"    valid_from DATE,\n",[855,1771,1772],{"class":857,"line":1624},[855,1773,1774],{},"    valid_to DATE,\n",[855,1776,1777],{"class":857,"line":1629},[855,1778,1779],{},"    PERIOD FOR validity (valid_from, valid_to)\n",[855,1781,1782],{"class":857,"line":1635},[855,1783,1784],{},");\n",[855,1786,1787],{"class":857,"line":1641},[855,1788,909],{"emptyLinePlaceholder":908},[855,1790,1791],{"class":857,"line":1647},[855,1792,1793],{},"-- Chỉ update premium trong tháng 6\n",[855,1795,1797],{"class":857,"line":1796},10,[855,1798,1799],{},"UPDATE policy FOR PORTION OF validity\n",[855,1801,1803],{"class":857,"line":1802},11,[855,1804,1805],{},"FROM '2026-06-01' TO '2026-06-30'\n",[855,1807,1809],{"class":857,"line":1808},12,[855,1810,1811],{},"SET premium = premium * 1.1\n",[855,1813,1815],{"class":857,"line":1814},13,[855,1816,1817],{},"WHERE id = 100;\n",[488,1819,1820,1821,1824,1825,1828],{},"Postgres tự động ",[443,1822,1823],{},"split row"," tại ranh giới khoảng thời gian — nếu row cũ có ",[580,1826,1827],{},"validity = [2026-01-01, 2026-12-31]",", sau UPDATE nó trở thành 3 row:",[1412,1830,1831,1837,1843],{},[440,1832,1833,1836],{},[580,1834,1835],{},"[2026-01-01, 2026-05-31]"," — giữ nguyên premium cũ.",[440,1838,1839,1842],{},[580,1840,1841],{},"[2026-06-01, 2026-06-30]"," — premium mới.",[440,1844,1845,1836],{},[580,1846,1847],{},"[2026-07-01, 2026-12-31]",[488,1849,1850],{},"Dùng cho: lịch sử giá, policy bảo hiểm, payroll theo kỳ.",[432,1852,1854],{"id":1853},"_64-group-by-all-làm-gì","64. GROUP BY ALL làm gì?",[488,1856,1857,1859,1860,1863],{},[580,1858,571],{}," tự động nhóm theo ",[443,1861,1862],{},"tất cả cột trong SELECT không phải aggregate",", giúp code sạch hơn khi có nhiều cột:",[846,1865,1867],{"className":848,"code":1866,"language":850,"meta":851,"style":851},"-- Trước PG 19\nSELECT department, city, job_level, AVG(salary)\nFROM employees\nGROUP BY department, city, job_level;\n\n-- PG 19 — ngắn hơn, tránh quên cột\nSELECT department, city, job_level, AVG(salary)\nFROM employees\nGROUP BY ALL;\n",[580,1868,1869,1874,1879,1884,1889,1893,1898,1902,1906],{"__ignoreMap":851},[855,1870,1871],{"class":857,"line":858},[855,1872,1873],{},"-- Trước PG 19\n",[855,1875,1876],{"class":857,"line":877},[855,1877,1878],{},"SELECT department, city, job_level, AVG(salary)\n",[855,1880,1881],{"class":857,"line":905},[855,1882,1883],{},"FROM employees\n",[855,1885,1886],{"class":857,"line":912},[855,1887,1888],{},"GROUP BY department, city, job_level;\n",[855,1890,1891],{"class":857,"line":1624},[855,1892,909],{"emptyLinePlaceholder":908},[855,1894,1895],{"class":857,"line":1629},[855,1896,1897],{},"-- PG 19 — ngắn hơn, tránh quên cột\n",[855,1899,1900],{"class":857,"line":1635},[855,1901,1878],{},[855,1903,1904],{"class":857,"line":1641},[855,1905,1883],{},[855,1907,1908],{"class":857,"line":1647},[855,1909,1910],{},"GROUP BY ALL;\n",[488,1912,1913,1914,1917],{},"Co giãn tốt: khi bạn thêm\u002Fxoá cột SELECT, không cần sửa GROUP BY. Giống như ",[580,1915,1916],{},"SELECT *"," nhưng cho GROUP BY.",[488,1919,1920,1923],{},[443,1921,1922],{},"Nhưng cẩn thận:"," Nếu SELECT có cột không mong muốn trong GROUP BY (vd: comment, note text), có thể tạo group sai. Vẫn nên xem lại output.",[432,1925,1927],{"id":1926},"_65-ignore-nulls-trong-window-function-những-hàm-nào-hỗ-trợ","65. IGNORE NULLS trong window function — những hàm nào hỗ trợ?",[488,1929,1930,1931,951,1933,1936],{},"PG 19 hỗ trợ ",[580,1932,577],{},[580,1934,1935],{},"RESPECT NULLS"," (default) cho các window function:",[437,1938,1939,1944,1949,1954,1959],{},[440,1940,1941],{},[580,1942,1943],{},"LAG(col IGNORE NULLS)",[440,1945,1946],{},[580,1947,1948],{},"LEAD(col IGNORE NULLS)",[440,1950,1951],{},[580,1952,1953],{},"FIRST_VALUE(col IGNORE NULLS)",[440,1955,1956],{},[580,1957,1958],{},"LAST_VALUE(col IGNORE NULLS)",[440,1960,1961],{},[580,1962,1963],{},"NTH_VALUE(col, n IGNORE NULLS)",[846,1965,1967],{"className":848,"code":1966,"language":850,"meta":851,"style":851},"SELECT\n    event_time,\n    LAG(price IGNORE NULLS) OVER (ORDER BY event_time) AS prev_price\nFROM stock_ticks;\n",[580,1968,1969,1974,1979,1984],{"__ignoreMap":851},[855,1970,1971],{"class":857,"line":858},[855,1972,1973],{},"SELECT\n",[855,1975,1976],{"class":857,"line":877},[855,1977,1978],{},"    event_time,\n",[855,1980,1981],{"class":857,"line":905},[855,1982,1983],{},"    LAG(price IGNORE NULLS) OVER (ORDER BY event_time) AS prev_price\n",[855,1985,1986],{"class":857,"line":912},[855,1987,1988],{},"FROM stock_ticks;\n",[488,1990,1991],{},"Bài toán điển hình: forward-fill \u002F backward-fill missing data trong time series, mang giá trị gần nhất không NULL lên.",[488,1993,1994,1995,1998,1999,2001],{},"Trước PG 19, bạn phải viết subquery hoặc ",[580,1996,1997],{},"COALESCE"," + ",[580,2000,582],{}," lồng nhau. Giờ sạch hơn và planner tối ưu tốt hơn.",[432,2003,2005],{"id":2004},"_66-pg_plan_advice-plan-hint-pg-19-khác-oraclemysql-ra-sao","66. pg_plan_advice — plan hint PG 19 khác Oracle\u002FMySQL ra sao?",[488,2007,2008,2010,2011,616],{},[580,2009,601],{}," là extension chính thức trong PG 19, cho phép gợi ý planner mà không cần extension bên thứ 3 như ",[580,2012,2013],{},"pg_hint_plan",[846,2015,2017],{"className":848,"code":2016,"language":850,"meta":851,"style":851},"-- Gợi ý dùng Index Scan\nSELECT \u002F*+ IndexScan(users) *\u002F * FROM users WHERE email = 'alice@example.com';\n\n-- Gợi ý dùng Hash Join\nSELECT \u002F*+ HashJoin(o u) *\u002F * FROM orders o JOIN users u ON o.user_id = u.id;\n\n-- Gợi ý song song hoá\nSELECT \u002F*+ Parallel(orders 4) *\u002F * FROM orders;\n",[580,2018,2019,2024,2029,2033,2038,2043,2047,2052],{"__ignoreMap":851},[855,2020,2021],{"class":857,"line":858},[855,2022,2023],{},"-- Gợi ý dùng Index Scan\n",[855,2025,2026],{"class":857,"line":877},[855,2027,2028],{},"SELECT \u002F*+ IndexScan(users) *\u002F * FROM users WHERE email = 'alice@example.com';\n",[855,2030,2031],{"class":857,"line":905},[855,2032,909],{"emptyLinePlaceholder":908},[855,2034,2035],{"class":857,"line":912},[855,2036,2037],{},"-- Gợi ý dùng Hash Join\n",[855,2039,2040],{"class":857,"line":1624},[855,2041,2042],{},"SELECT \u002F*+ HashJoin(o u) *\u002F * FROM orders o JOIN users u ON o.user_id = u.id;\n",[855,2044,2045],{"class":857,"line":1629},[855,2046,909],{"emptyLinePlaceholder":908},[855,2048,2049],{"class":857,"line":1635},[855,2050,2051],{},"-- Gợi ý song song hoá\n",[855,2053,2054],{"class":857,"line":1641},[855,2055,2056],{},"SELECT \u002F*+ Parallel(orders 4) *\u002F * FROM orders;\n",[488,2058,2059],{},"Khác với Oracle\u002FMySQL hint:",[437,2061,2062,2069,2072],{},[440,2063,2064,2065,2068],{},"PG hint là ",[443,2066,2067],{},"gợi ý mềm"," (advice), planner vẫn có quyền từ chối nếu thấy không hợp lý.",[440,2070,2071],{},"Oracle hint cứng hơn — planner gần như bắt buộc tuân theo.",[440,2073,2074],{},"PG hint không thay đổi semantic của query, chỉ ảnh hưởng plan.",[972,2076,2077,2078,2080],{"color":974,"icon":975},"Nên dùng ",[580,2079,601],{}," như giải pháp cuối cùng (last resort). Trước đó: ANALYZE, tune statistic, viết lại query, tạo index phù hợp.",[432,2082,2084],{"id":2083},"_67-repack-table-concurrently-khác-vacuum-full-thế-nào","67. REPACK TABLE CONCURRENTLY khác VACUUM FULL thế nào?",[488,2086,2087,2089,2090,2093],{},[580,2088,615],{}," rebuild toàn bộ bảng để reclaim space do bloat, nhưng ",[443,2091,2092],{},"lock exclusive (AccessExclusive)"," — bảng không thể đọc\u002Fghi trong suốt quá trình.",[488,2095,2096,2098,2099,994],{},[580,2097,611],{}," (PG 19) rebuild bảng ",[443,2100,2101],{},"không lock",[846,2103,2105],{"className":848,"code":2104,"language":850,"meta":851,"style":851},"REPACK TABLE CONCURRENTLY orders;\n",[580,2106,2107],{"__ignoreMap":851},[855,2108,2109],{"class":857,"line":858},[855,2110,2104],{},[488,2112,2113],{},"Cách hoạt động:",[1412,2115,2116,2119,2122,2125],{},[440,2117,2118],{},"Tạo bảng mới với cấu trúc giống bảng cũ.",[440,2120,2121],{},"Copy row sang bảng mới (chỉ row live, bỏ dead tuple).",[440,2123,2124],{},"Trigger + log để sync thay đổi trong lúc copy.",[440,2126,2127],{},"Swap metadata — atomic, gần như không downtime.",[2129,2130,2131,2145],"table",{},[2132,2133,2134],"thead",{},[2135,2136,2137,2140,2142],"tr",{},[2138,2139],"th",{},[2138,2141,615],{},[2138,2143,2144],{},"REPACK CONCURRENTLY",[2146,2147,2148,2160,2171,2181],"tbody",{},[2135,2149,2150,2154,2157],{},[2151,2152,2153],"td",{},"Lock",[2151,2155,2156],{},"AccessExclusive",[2151,2158,2159],{},"Không lock đọc\u002Fghi",[2135,2161,2162,2165,2168],{},[2151,2163,2164],{},"Downtime",[2151,2166,2167],{},"Có (vài phút đến vài giờ)",[2151,2169,2170],{},"Gần như không",[2135,2172,2173,2176,2179],{},[2151,2174,2175],{},"Disk space",[2151,2177,2178],{},"Cần ~2x size bảng",[2151,2180,2178],{},[2135,2182,2183,2186,2189],{},[2151,2184,2185],{},"MVCC",[2151,2187,2188],{},"Transactional",[2151,2190,2188],{},[432,2192,2194],{"id":2193},"_68-parallel-autovacuum-cơ-chế-và-mặc-định-ra-sao","68. Parallel Autovacuum — cơ chế và mặc định ra sao?",[488,2196,2197,2198,2201],{},"Trước PG 19, autovacuum chạy ",[443,2199,2200],{},"single worker"," cho mỗi bảng. Với bảng lớn, throughput cao (UPDATE\u002FDELETE liên tục), một worker không kịp → bloat tích luỹ.",[488,2203,2204,2205,2208],{},"PG 19 cho phép ",[443,2206,2207],{},"nhiều autovacuum worker"," chạy song song trên cùng một bảng, chia theo page range:",[846,2210,2215],{"className":2211,"code":2213,"language":2214},[2212],"language-text","autovacuum_max_parallel_workers = 3      -- (mặc định)\nautovacuum_parallel_cost_delay = 2ms\nautovacuum_parallel_cost_limit = 200\n","text",[580,2216,2213],{"__ignoreMap":851},[488,2218,2219],{},"Cơ chế:",[437,2221,2222,2225,2228],{},[440,2223,2224],{},"Leader worker quét visibility map, xác định page có dead tuple.",[440,2226,2227],{},"Chia page range cho parallel workers.",[440,2229,2230],{},"Mỗi worker VACUUM range của mình độc lập.",[972,2232,2233,2234,2237,2238,951,2241,2244],{"color":974,"icon":975},"Parallel autovacuum ",[443,2235,2236],{},"không bật mặc định"," trong PG 19. Cần cấu hình ",[580,2239,2240],{},"autovacuum_max_parallel_workers >= 2",[580,2242,2243],{},"vacuum_parallel"," trong storage parameter của bảng.",[432,2246,2248],{"id":2247},"_69-json-copy-to-hỗ-trợ-format-nào","69. JSON COPY TO hỗ trợ format nào?",[488,2250,2251,2252,2255],{},"PG 19 mở rộng ",[580,2253,2254],{},"COPY TO"," để export trực tiếp ra JSON:",[846,2257,2259],{"className":848,"code":2258,"language":850,"meta":851,"style":851},"COPY orders TO '\u002Ftmp\u002Forders.json' (FORMAT JSON);\nCOPY orders TO '\u002Ftmp\u002Forders.jsonl' (FORMAT JSON, LINESEPARATOR E'\\n');\n",[580,2260,2261,2266],{"__ignoreMap":851},[855,2262,2263],{"class":857,"line":858},[855,2264,2265],{},"COPY orders TO '\u002Ftmp\u002Forders.json' (FORMAT JSON);\n",[855,2267,2268],{"class":857,"line":877},[855,2269,2270],{},"COPY orders TO '\u002Ftmp\u002Forders.jsonl' (FORMAT JSON, LINESEPARATOR E'\\n');\n",[488,2272,2273],{},"Hỗ trợ:",[437,2275,2276,2285,2291,2297],{},[440,2277,2278,2281,2282,616],{},[443,2279,2280],{},"JSON array"," (mặc định): toàn bộ kết quả trong ",[580,2283,2284],{},"[{...}, {...}]",[440,2286,2287,2290],{},[443,2288,2289],{},"JSONL"," (JSON Lines): mỗi row một dòng JSON object, phù hợp cho streaming processing.",[440,2292,2293,2296],{},[443,2294,2295],{},"JSON columns",": có thể chỉ export một số cột, hoặc toàn bộ.",[440,2298,2299,2302,2303,2306],{},[443,2300,2301],{},"Nested JSON",": dùng subquery với ",[580,2304,2305],{},"jsonb_build_object()"," để tạo cấu trúc phức tạp.",[846,2308,2310],{"className":848,"code":2309,"language":850,"meta":851,"style":851},"COPY (\n    SELECT jsonb_build_object('id', id, 'items', items)\n    FROM orders\n) TO '\u002Ftmp\u002Forders_nested.jsonl' (FORMAT JSON);\n",[580,2311,2312,2317,2322,2327],{"__ignoreMap":851},[855,2313,2314],{"class":857,"line":858},[855,2315,2316],{},"COPY (\n",[855,2318,2319],{"class":857,"line":877},[855,2320,2321],{},"    SELECT jsonb_build_object('id', id, 'items', items)\n",[855,2323,2324],{"class":857,"line":905},[855,2325,2326],{},"    FROM orders\n",[855,2328,2329],{"class":857,"line":912},[855,2330,2331],{},") TO '\u002Ftmp\u002Forders_nested.jsonl' (FORMAT JSON);\n",[488,2333,2334,2335,1998,2338,2341],{},"Trước PG 19, bạn phải dùng ",[580,2336,2337],{},"json_agg()",[580,2339,2340],{},"COPY (SELECT ...)"," hoặc script external. Giờ tiện hơn, nhanh hơn (C level, không qua SQL aggregation).",[432,2343,2345],{"id":2344},"_70-online-data-checksums-bật-checksum-không-downtime","70. Online Data Checksums — bật checksum không downtime?",[488,2347,2348],{},"PG checksum bảo vệ dữ liệu khỏi corruption ở mức page (8KB). Trước PG 19, để bật checksum:",[1412,2350,2351,2354,2360],{},[440,2352,2353],{},"Shutdown cluster.",[440,2355,2356,2357,616],{},"Chạy ",[580,2358,2359],{},"pg_checksums --enable",[440,2361,2362],{},"Start lại.",[488,2364,2365,2366,2369],{},"→ ",[443,2367,2368],{},"Downtime."," Trên DB nhiều TB, bước 2 có thể mất hàng giờ.",[488,2371,2204,2372,994],{},[443,2373,2374],{},"bật checksum online",[846,2376,2378],{"className":848,"code":2377,"language":850,"meta":851,"style":851},"ALTER SYSTEM SET data_checksums = on;\nSELECT pg_enable_data_checksums();\n-- Kiểm tra tiến độ\nSELECT * FROM pg_stat_enable_checksums;\n",[580,2379,2380,2385,2390,2395],{"__ignoreMap":851},[855,2381,2382],{"class":857,"line":858},[855,2383,2384],{},"ALTER SYSTEM SET data_checksums = on;\n",[855,2386,2387],{"class":857,"line":877},[855,2388,2389],{},"SELECT pg_enable_data_checksums();\n",[855,2391,2392],{"class":857,"line":905},[855,2393,2394],{},"-- Kiểm tra tiến độ\n",[855,2396,2397],{"class":857,"line":912},[855,2398,2399],{},"SELECT * FROM pg_stat_enable_checksums;\n",[488,2401,2113],{},[437,2403,2404,2407,2410,2413],{},[440,2405,2406],{},"Background worker quét tất cả page trong data directory.",[440,2408,2409],{},"Mỗi page được đọc, tính checksum, ghi lại — từng page một.",[440,2411,2412],{},"Bảng vẫn đọc\u002Fghi bình thường trong suốt quá trình.",[440,2414,2415],{},"Sau khi hoàn tất, mọi page mới tự động có checksum.",[972,2417,2419],{"color":1723,"icon":2418},"i-lucide-shield-check","Luôn bật checksum trên production. Phát hiện corruption sớm ngăn backup cũng bị corrupt theo.",[972,2421,2423,2424],{"color":974,"icon":2422},"i-lucide-arrow-right","Tiếp theo: ",[2425,2426,2427],"a",{"href":220},"Tích hợp PostgreSQL với C# (Npgsql)",[2429,2430,2431],"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":851,"searchDepth":877,"depth":877,"links":2433},[2434,2439,2448,2456,2463,2469,2478,2488,2495,2501,2508,2512,2520],{"id":429,"depth":877,"text":430,"children":2435},[2436,2437,2438],{"id":434,"depth":905,"text":435},{"id":485,"depth":905,"text":486},{"id":637,"depth":905,"text":638},{"id":644,"depth":877,"text":645,"children":2440},[2441,2442,2443,2444,2445,2446,2447],{"id":648,"depth":905,"text":649},{"id":665,"depth":905,"text":666},{"id":690,"depth":905,"text":691},{"id":713,"depth":905,"text":714},{"id":723,"depth":905,"text":724},{"id":748,"depth":905,"text":749},{"id":755,"depth":905,"text":756},{"id":783,"depth":877,"text":784,"children":2449},[2450,2451,2452,2453,2454,2455],{"id":787,"depth":905,"text":788},{"id":806,"depth":905,"text":807},{"id":829,"depth":905,"text":830},{"id":840,"depth":905,"text":841},{"id":863,"depth":905,"text":864},{"id":883,"depth":905,"text":884},{"id":918,"depth":877,"text":919,"children":2457},[2458,2459,2460,2461,2462],{"id":922,"depth":905,"text":923},{"id":936,"depth":905,"text":937},{"id":943,"depth":905,"text":944},{"id":986,"depth":905,"text":987},{"id":1012,"depth":905,"text":1013},{"id":1036,"depth":877,"text":1037,"children":2464},[2465,2466,2467,2468],{"id":1040,"depth":905,"text":1041},{"id":1047,"depth":905,"text":1048},{"id":1069,"depth":905,"text":1070},{"id":1088,"depth":905,"text":1089},{"id":1109,"depth":877,"text":1110,"children":2470},[2471,2472,2473,2474,2475,2476,2477],{"id":1113,"depth":905,"text":1114},{"id":1120,"depth":905,"text":1121},{"id":1127,"depth":905,"text":1128},{"id":1134,"depth":905,"text":1135},{"id":1150,"depth":905,"text":1151},{"id":1166,"depth":905,"text":1167},{"id":1173,"depth":905,"text":1174},{"id":1180,"depth":877,"text":1181,"children":2479},[2480,2481,2482,2483,2484,2485,2486,2487],{"id":1184,"depth":905,"text":1185},{"id":1194,"depth":905,"text":1195},{"id":1201,"depth":905,"text":1202},{"id":1211,"depth":905,"text":1212},{"id":1218,"depth":905,"text":1219},{"id":1225,"depth":905,"text":1226},{"id":1232,"depth":905,"text":1233},{"id":1239,"depth":905,"text":1240},{"id":1249,"depth":877,"text":1250,"children":2489},[2490,2491,2493,2494],{"id":1253,"depth":905,"text":1254},{"id":1271,"depth":905,"text":2492},"42. JSON operator -> vs ->>?",{"id":1295,"depth":905,"text":1296},{"id":1309,"depth":905,"text":1310},{"id":1323,"depth":877,"text":1324,"children":2496},[2497,2498,2499,2500],{"id":1327,"depth":905,"text":1328},{"id":1334,"depth":905,"text":1335},{"id":1352,"depth":905,"text":1353},{"id":1359,"depth":905,"text":1360},{"id":1369,"depth":877,"text":1370,"children":2502},[2503,2504,2505,2506,2507],{"id":1373,"depth":905,"text":1374},{"id":1391,"depth":905,"text":1392},{"id":1409,"depth":905,"text":1410},{"id":1431,"depth":905,"text":1432},{"id":1438,"depth":905,"text":1439},{"id":1462,"depth":877,"text":1463,"children":2509},[2510,2511],{"id":1466,"depth":905,"text":1467},{"id":1484,"depth":905,"text":1485},{"id":1496,"depth":877,"text":1497,"children":2513},[2514,2516,2517,2518,2519],{"id":1500,"depth":905,"text":2515},"56. Bảng 100M row, query WHERE LOWER(email) = ? rất chậm. Fix?",{"id":1514,"depth":905,"text":1515},{"id":1535,"depth":905,"text":1536},{"id":1556,"depth":905,"text":1557},{"id":1567,"depth":905,"text":1568},{"id":1574,"depth":877,"text":1575,"children":2521},[2522,2523,2524,2525,2526,2527,2528,2529,2530,2531],{"id":1578,"depth":905,"text":1579},{"id":1656,"depth":905,"text":1657},{"id":1734,"depth":905,"text":1735},{"id":1853,"depth":905,"text":1854},{"id":1926,"depth":905,"text":1927},{"id":2004,"depth":905,"text":2005},{"id":2083,"depth":905,"text":2084},{"id":2193,"depth":905,"text":2194},{"id":2247,"depth":905,"text":2248},{"id":2344,"depth":905,"text":2345},"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.","md",null,{},{"title":193,"icon":196},{"title":422,"description":2532},"qXowNtiLsuawJqewuDnM9PZaz1_iayiCVx1qodJoGk8",[2540,2542],{"title":188,"path":213,"stem":214,"description":2541,"icon":191,"children":-1},"Feature riêng Postgres — JSONB, array, range, extension (pgvector, PostGIS, pg_trgm), partial\u002Fexpression index, performance tuning.",{"title":219,"path":220,"stem":221,"description":2543,"icon":96,"children":-1},"Hướng dẫn toàn diện kết nối PostgreSQL từ C# dùng Npgsql — CRUD, transaction, gọi function\u002Fstored procedure, import CSV. Dành cho dev .NET.",1783490365912]