@umacloud/knowledge 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/00-governance/governance-capabilities.md +557 -0
- package/00-governance/knowledge-map.md +39 -0
- package/00-governance/maintenance-policy.md +76 -0
- package/00-governance/review-checklist.md +81 -0
- package/README.md +13 -0
- package/ai/01-standards/agent-development-complete.md +691 -0
- package/ai/01-standards/llm-application-complete.md +488 -0
- package/ai/01-standards/mlops-complete.md +798 -0
- package/ai/01-standards/prompt-engineering-complete.md +646 -0
- package/ai/01-standards/rag-architecture-complete.md +649 -0
- package/ai/02-playbooks/llm-evaluation-playbook.md +847 -0
- package/ai/03-checklists/ai-project-checklist.md +215 -0
- package/ai/04-antipatterns/ai-antipatterns.md +661 -0
- package/ai/05-cases/case-rag-production.md +147 -0
- package/ai/06-glossary/ai-glossary.md +162 -0
- package/ai/agent-evaluation-benchmark.md +53 -0
- package/ai/ai-agent-memory-context-management.md +41 -0
- package/ai/ai-cost-capacity-optimization-playbook.md +42 -0
- package/ai/ai-data-security-and-compliance-playbook.md +37 -0
- package/ai/ai-domain-index-and-checklist.md +40 -0
- package/ai/ai-governance-maturity-model.md +50 -0
- package/ai/ai-model-selection-and-routing-strategy.md +47 -0
- package/ai/ai-observability-and-oncall-runbook.md +52 -0
- package/ai/ai-rag-engineering-playbook.md +42 -0
- package/ai/ai-red-team-and-safety-evaluation.md +42 -0
- package/ai/ai-release-readiness-and-rollback-gate.md +42 -0
- package/ai/llm-agent-engineering-deep-dive.md +57 -0
- package/ai/prompt-and-tool-guardrails.md +52 -0
- package/api/01-standards/enterprise-api-standards.md +198 -0
- package/api/01-standards/rest-api-design-guide.md +63 -0
- package/api/02-playbooks/api-pagination-playbook.md +93 -0
- package/api/02-playbooks/graphql-production-playbook.md +176 -0
- package/api/03-checklists/api-review-checklist.md +55 -0
- package/api/04-antipatterns/api-antipatterns.md +112 -0
- package/architecture/01-standards/api-gateway-patterns.md +496 -0
- package/architecture/01-standards/cloud-native-patterns.md +644 -0
- package/architecture/01-standards/distributed-systems-patterns.md +591 -0
- package/architecture/01-standards/event-driven-architecture.md +595 -0
- package/architecture/01-standards/microservices-patterns-complete.md +968 -0
- package/architecture/01-standards/microservices-patterns.md +495 -0
- package/architecture/01-standards/system-design-interview.md +664 -0
- package/architecture/02-playbooks/microservices-patterns-playbook.md +137 -0
- package/architecture/02-playbooks/migration-playbook.md +780 -0
- package/architecture/02-playbooks/system-design-playbook.md +779 -0
- package/architecture/03-checklists/architecture-decision-checklist.md +297 -0
- package/architecture/04-antipatterns/architecture-antipatterns.md +417 -0
- package/architecture/05-cases/case-netflix-microservices.md +413 -0
- package/architecture/06-glossary/architecture-glossary.md +164 -0
- package/architecture/adr-template-and-examples.md +38 -0
- package/architecture/api-gateway-deep-dive.md +1291 -0
- package/architecture/configuration-management.md +1162 -0
- package/architecture/distributed-transactions.md +1220 -0
- package/architecture/microservices-complete.md +735 -0
- package/architecture/resilience-and-disaster-patterns.md +37 -0
- package/architecture/service-governance.md +1198 -0
- package/architecture/system-architecture-deep-dive.md +37 -0
- package/backend/01-standards/analytics-and-growth.md +65 -0
- package/backend/01-standards/api-and-error-conventions.md +120 -0
- package/backend/01-standards/application-layering-and-packaging.md +160 -0
- package/backend/01-standards/auth-implementation.md +104 -0
- package/backend/01-standards/backend-framework-idioms.md +74 -0
- package/backend/01-standards/background-jobs-and-async.md +66 -0
- package/backend/01-standards/caching-strategies-complete.md +390 -0
- package/backend/01-standards/config-and-observability.md +77 -0
- package/backend/01-standards/data-modeling-and-persistence.md +94 -0
- package/backend/01-standards/django-complete.md +1765 -0
- package/backend/01-standards/email-and-notifications.md +64 -0
- package/backend/01-standards/fastapi-complete.md +925 -0
- package/backend/01-standards/file-upload-and-storage.md +66 -0
- package/backend/01-standards/graphql-api-complete.md +416 -0
- package/backend/01-standards/llm-application-standard.md +78 -0
- package/backend/01-standards/message-queue-patterns.md +379 -0
- package/backend/01-standards/microservices-and-distributed.md +78 -0
- package/backend/01-standards/nestjs-complete.md +2167 -0
- package/backend/01-standards/payment-integration.md +80 -0
- package/backend/01-standards/rate-limiting-complete.md +451 -0
- package/backend/01-standards/realtime-and-websocket.md +65 -0
- package/backend/01-standards/search-and-filtering.md +64 -0
- package/backend/01-standards/spring-boot-complete.md +445 -0
- package/backend/02-playbooks/api-design-playbook.md +718 -0
- package/backend/02-playbooks/email-send-playbook.md +130 -0
- package/backend/02-playbooks/file-upload-s3-playbook.md +153 -0
- package/backend/02-playbooks/typescript-enterprise-playbook.md +133 -0
- package/backend/02-playbooks/websocket-realtime-playbook.md +154 -0
- package/backend/03-checklists/api-launch-checklist.md +189 -0
- package/backend/04-antipatterns/backend-antipatterns.md +1051 -0
- package/blockchain/01-standards/blockchain-basics.md +557 -0
- package/blockchain/01-standards/smart-contract-development.md +1315 -0
- package/cicd/01-standards/deployment-and-delivery-standard.md +96 -0
- package/cicd/01-standards/github-actions-complete.md +473 -0
- package/cicd/01-standards/release-and-store-submission.md +75 -0
- package/cicd/02-playbooks/cicd-pipeline-playbook.md +144 -0
- package/cicd/02-playbooks/release-management-playbook.md +605 -0
- package/cicd/03-checklists/pipeline-security-checklist.md +168 -0
- package/cicd/04-antipatterns/cicd-antipatterns.md +589 -0
- package/cicd/05-cases/case-deployment-automation.md +221 -0
- package/cicd/05-cases/case-gitops-transformation.md +212 -0
- package/cicd/06-glossary/cicd-glossary.md +114 -0
- package/cicd/cicd-blueprint-deep-dive.md +38 -0
- package/cicd/release-readiness-gate.md +37 -0
- package/cloud-native/01-standards/container-security.md +741 -0
- package/cloud-native/01-standards/kubernetes-complete.md +812 -0
- package/cloud-native/02-playbooks/api-gateway-playbook.md +155 -0
- package/cloud-native/02-playbooks/gitops-with-argocd.md +760 -0
- package/cloud-native/02-playbooks/k8s-troubleshooting-playbook.md +1942 -0
- package/cloud-native/02-playbooks/message-queue-playbook.md +129 -0
- package/cloud-native/02-playbooks/multicloud-governance.md +726 -0
- package/cloud-native/02-playbooks/serverless-patterns.md +788 -0
- package/cloud-native/02-playbooks/service-mesh-playbook.md +612 -0
- package/cloud-native/02-playbooks/terraform-iac-playbook.md +143 -0
- package/cloud-native/03-checklists/container-security-checklist.md +431 -0
- package/cloud-native/03-checklists/k8s-production-readiness-checklist.md +460 -0
- package/cloud-native/04-antipatterns/container-antipatterns.md +660 -0
- package/cloud-native/04-antipatterns/k8s-antipatterns.md +743 -0
- package/cloud-native/05-cases/case-k8s-migration.md +478 -0
- package/cloud-native/05-cases/case-k8s-scaling.md +642 -0
- package/cloud-native/05-cases/case-k8s-security-incident.md +397 -0
- package/cloud-native/06-glossary/cloud-native-glossary.md +337 -0
- package/cross-platform/01-standards/cross-platform-frameworks.md +83 -0
- package/cross-platform/01-standards/platform-selection-and-architecture.md +77 -0
- package/data/01-standards/elasticsearch-complete.md +2098 -0
- package/data/01-standards/postgresql-complete.md +1613 -0
- package/data/01-standards/redis-complete.md +1527 -0
- package/data/02-playbooks/database-optimization-playbook.md +403 -0
- package/data/02-playbooks/elasticsearch-production-playbook.md +132 -0
- package/data/03-checklists/database-launch-checklist.md +187 -0
- package/data/04-antipatterns/database-antipatterns.md +873 -0
- package/data/05-cases/case-database-migration.md +310 -0
- package/data/06-glossary/database-glossary.md +440 -0
- package/data/data-governance-and-modeling-deep-dive.md +39 -0
- package/data-engineering/01-standards/airflow-complete.md +523 -0
- package/data-engineering/01-standards/kafka-complete.md +1521 -0
- package/data-engineering/02-playbooks/spark-etl-playbook.md +496 -0
- package/data-engineering/03-checklists/pipeline-launch-checklist.md +194 -0
- package/data-engineering/04-antipatterns/data-pipeline-antipatterns.md +684 -0
- package/data-engineering/05-cases/case-real-time-pipeline.md +355 -0
- package/data-engineering/06-glossary/data-engineering-glossary.md +429 -0
- package/database/01-standards/database-schema-standards.md +147 -0
- package/database/02-playbooks/postgresql-optimization-quick.md +52 -0
- package/database/02-playbooks/postgresql-performance-optimization.md +58 -0
- package/database/02-playbooks/postgresql-production-playbook.md +146 -0
- package/database/02-playbooks/redis-caching-playbook.md +117 -0
- package/database/03-checklists/database-review-checklist.md +50 -0
- package/database/04-antipatterns/database-antipatterns.md +112 -0
- package/design/01-standards/ui-design-system-complete.md +423 -0
- package/design/02-playbooks/design-handoff-playbook.md +254 -0
- package/design/02-playbooks/design-review-playbook.md +388 -0
- package/design/03-checklists/design-review-checklist.md +246 -0
- package/design/04-antipatterns/design-antipatterns.md +378 -0
- package/design/05-cases/case-design-system-adoption.md +328 -0
- package/design/06-glossary/design-glossary.md +329 -0
- package/design/ui-full-lifecycle-cross-platform-playbook.md +571 -0
- package/design/ux-system-deep-dive.md +38 -0
- package/design-systems/00-craft-rules.md +71 -0
- package/design-systems/aesthetic-families.md +43 -0
- package/design-systems/anti-ai-slop.md +162 -0
- package/design-systems/bold-geometric.md +120 -0
- package/design-systems/brutalist-bold.md +103 -0
- package/design-systems/editorial-clean.md +109 -0
- package/design-systems/glass-aurora.md +108 -0
- package/design-systems/modern-minimal.md +145 -0
- package/design-systems/premium-luxury.md +106 -0
- package/design-systems/product-type-design-map.md +48 -0
- package/design-systems/soft-warm.md +123 -0
- package/design-systems/tech-utility.md +113 -0
- package/desktop/01-standards/desktop-app-standard.md +72 -0
- package/desktop/01-standards/desktop-design.md +71 -0
- package/development/00-governance/document-template.md +41 -0
- package/development/01-standards/api-versioning-strategies.md +432 -0
- package/development/01-standards/authentication-patterns-complete.md +479 -0
- package/development/01-standards/css-architecture-complete.md +550 -0
- package/development/01-standards/database-migration-strategies.md +484 -0
- package/development/01-standards/elasticsearch-complete.md +347 -0
- package/development/01-standards/git-complete.md +371 -0
- package/development/01-standards/golang-complete.md +1565 -0
- package/development/01-standards/graphql-complete.md +298 -0
- package/development/01-standards/javascript-bundlers-complete.md +469 -0
- package/development/01-standards/javascript-typescript-complete.md +528 -0
- package/development/01-standards/jest-complete.md +275 -0
- package/development/01-standards/linux-complete.md +234 -0
- package/development/01-standards/logging-observability-complete.md +526 -0
- package/development/01-standards/microservices-communication.md +502 -0
- package/development/01-standards/mongodb-complete.md +406 -0
- package/development/01-standards/oauth2-complete.md +285 -0
- package/development/01-standards/performance-optimization-complete.md +289 -0
- package/development/01-standards/playwright-complete.md +247 -0
- package/development/01-standards/postgresql-complete.md +456 -0
- package/development/01-standards/pytest-complete.md +340 -0
- package/development/01-standards/python-async-programming.md +902 -0
- package/development/01-standards/python-complete.md +956 -0
- package/development/01-standards/python-decorators-complete.md +799 -0
- package/development/01-standards/python-design-patterns.md +2854 -0
- package/development/01-standards/python-packaging-distribution.md +420 -0
- package/development/01-standards/python-testing-strategies.md +607 -0
- package/development/01-standards/python-web-frameworks-comparison.md +471 -0
- package/development/01-standards/redis-complete.md +317 -0
- package/development/01-standards/rest-api-complete.md +316 -0
- package/development/01-standards/rust-complete.md +578 -0
- package/development/01-standards/typescript-advanced-types.md +1513 -0
- package/development/01-standards/web-security-complete.md +292 -0
- package/development/02-playbooks/api-design-playbook.md +810 -0
- package/development/02-playbooks/database-migration-playbook.md +580 -0
- package/development/02-playbooks/debugging-playbook.md +692 -0
- package/development/02-playbooks/feature-delivery-playbook.md +430 -0
- package/development/02-playbooks/incident-hotfix-playbook.md +387 -0
- package/development/02-playbooks/performance-optimization-playbook.md +531 -0
- package/development/02-playbooks/performance-tuning-playbook.md +652 -0
- package/development/02-playbooks/refactor-playbook.md +403 -0
- package/development/02-playbooks/release-playbook.md +469 -0
- package/development/03-checklists/architecture-review-checklist.md +168 -0
- package/development/03-checklists/data-migration-checklist.md +157 -0
- package/development/03-checklists/oncall-handover-checklist.md +173 -0
- package/development/03-checklists/pr-checklist.md +158 -0
- package/development/03-checklists/production-readiness-checklist.md +190 -0
- package/development/03-checklists/release-readiness-checklist.md +154 -0
- package/development/03-checklists/security-review-checklist.md +182 -0
- package/development/04-antipatterns/api-antipatterns.md +657 -0
- package/development/04-antipatterns/architecture-antipatterns.md +686 -0
- package/development/04-antipatterns/backend-antipatterns.md +648 -0
- package/development/04-antipatterns/cicd-antipatterns.md +540 -0
- package/development/04-antipatterns/code-smell-antipatterns.md +571 -0
- package/development/04-antipatterns/data-antipatterns.md +658 -0
- package/development/04-antipatterns/database-antipatterns.md +578 -0
- package/development/04-antipatterns/frontend-antipatterns.md +635 -0
- package/development/04-antipatterns/reliability-antipatterns.md +700 -0
- package/development/04-antipatterns/security-antipatterns.md +747 -0
- package/development/05-cases/case-api-version-migration.md +428 -0
- package/development/05-cases/case-authorization-hardening.md +383 -0
- package/development/05-cases/case-bluegreen-rollback.md +466 -0
- package/development/05-cases/case-cache-snowball-protection.md +485 -0
- package/development/05-cases/case-ci-cd-pipeline.md +544 -0
- package/development/05-cases/case-database-scaling.md +500 -0
- package/development/05-cases/case-db-hotspot-optimization.md +487 -0
- package/development/05-cases/case-incident-mttr-reduction.md +563 -0
- package/development/05-cases/case-microservice-migration.md +375 -0
- package/development/05-cases/case-performance-optimization.md +406 -0
- package/development/05-cases/case-security-incident-response.md +345 -0
- package/development/06-glossary/full-stack-glossary.md +166 -0
- package/development/09-maturity/quarterly-audit-template.md +35 -0
- package/development/11-ui-excellence/ui-aesthetic-system.md +41 -0
- package/development/11-ui-excellence/ui-engineering-excellence.md +435 -0
- package/development/12-scenarios/development-scenarios-guide.md +565 -0
- package/development/13-implementation-assets/implementation-toolkit.md +282 -0
- package/development/13-implementation-assets/knowledge-gates-execution.md +43 -0
- package/development/14-full-lifecycle/software-lifecycle-gates.md +511 -0
- package/development/15-lifecycle-templates/project-templates-collection.md +791 -0
- package/development/api-contract-and-versioning-guide.md +36 -0
- package/development/api-governance-complete.md +43 -0
- package/development/backend-engineering-complete.md +43 -0
- package/development/code-review-quality-complete.md +43 -0
- package/development/concurrency-reliability-complete.md +43 -0
- package/development/database-engineering-complete.md +43 -0
- package/development/engineering-effectiveness-complete.md +43 -0
- package/development/engineering-standards-deep-dive.md +38 -0
- package/development/frontend-engineering-complete.md +43 -0
- package/development/performance-capacity-complete.md +43 -0
- package/development/refactor-migration-complete.md +42 -0
- package/development/refactoring-and-techdebt-playbook.md +37 -0
- package/development/security-in-development-complete.md +43 -0
- package/devops/01-standards/cicd-pipeline-complete.md +262 -0
- package/devops/01-standards/docker-complete.md +1490 -0
- package/devops/01-standards/github-actions-complete.md +337 -0
- package/devops/01-standards/kubernetes-complete.md +638 -0
- package/devops/01-standards/terraform-complete.md +2117 -0
- package/devops/02-playbooks/docker-compose-playbook.md +233 -0
- package/devops/02-playbooks/docker-k8s-production-playbook.md +186 -0
- package/devops/02-playbooks/docker-production-playbook.md +952 -0
- package/edge-iot/01-standards/edge-iot-complete.md +473 -0
- package/experts/architect/api-design.md +178 -0
- package/experts/architect/methodology.md +124 -0
- package/experts/architect/security.md +75 -0
- package/experts/backend-lead/methodology.md +216 -0
- package/experts/devops/methodology.md +160 -0
- package/experts/frontend-lead/methodology.md +178 -0
- package/experts/product-manager/industry/ecommerce.md +43 -0
- package/experts/product-manager/industry/saas.md +40 -0
- package/experts/product-manager/methodology.md +97 -0
- package/experts/qa-lead/methodology.md +123 -0
- package/experts/qa-lead/test-strategy.md +128 -0
- package/experts/uiux-designer/methodology.md +125 -0
- package/frontend/01-standards/accessibility-complete.md +532 -0
- package/frontend/01-standards/accessibility-standard.md +74 -0
- package/frontend/01-standards/admin-dashboard-and-crud.md +72 -0
- package/frontend/01-standards/design-tokens-complete.md +444 -0
- package/frontend/01-standards/forms-and-validation.md +77 -0
- package/frontend/01-standards/frontend-architecture-and-layering.md +119 -0
- package/frontend/01-standards/i18n-and-localization.md +65 -0
- package/frontend/01-standards/nextjs-complete.md +451 -0
- package/frontend/01-standards/react-complete.md +713 -0
- package/frontend/01-standards/react-hooks-complete-guide.md +1100 -0
- package/frontend/01-standards/react-hooks-complete.md +1171 -0
- package/frontend/01-standards/seo-and-web-vitals.md +77 -0
- package/frontend/01-standards/state-management-complete.md +444 -0
- package/frontend/01-standards/vue-complete.md +499 -0
- package/frontend/01-standards/vue3-complete.md +2002 -0
- package/frontend/01-standards/web-framework-best-practices.md +64 -0
- package/frontend/01-standards/web-performance-complete.md +495 -0
- package/frontend/02-playbooks/accessibility-a11y-playbook.md +161 -0
- package/frontend/02-playbooks/frontend-performance-playbook.md +707 -0
- package/frontend/02-playbooks/i18n-internationalization-playbook.md +120 -0
- package/frontend/02-playbooks/performance-optimization-playbook.md +163 -0
- package/frontend/02-playbooks/react-nextjs-production-playbook.md +167 -0
- package/frontend/02-playbooks/react-state-management-playbook.md +173 -0
- package/frontend/03-checklists/component-quality-checklist.md +166 -0
- package/frontend/03-checklists/frontend-launch-checklist.md +299 -0
- package/frontend/04-antipatterns/frontend-antipatterns.md +886 -0
- package/frontend/05-cases/case-performance-optimization.md +274 -0
- package/harmony/01-standards/harmonyos-arkts-standard.md +75 -0
- package/harmony/01-standards/harmonyos-design.md +65 -0
- package/high-quality-engineering-playbook.md +54 -0
- package/incident/01-standards/incident-response-complete.md +303 -0
- package/incident/02-playbooks/chaos-engineering-playbook.md +883 -0
- package/incident/02-playbooks/postmortem-playbook.md +398 -0
- package/incident/03-checklists/incident-readiness-checklist.md +181 -0
- package/incident/04-antipatterns/incident-antipatterns.md +490 -0
- package/incident/05-cases/case-cascade-failure.md +176 -0
- package/incident/06-glossary/incident-glossary.md +114 -0
- package/incident/postmortem-and-response-deep-dive.md +39 -0
- package/industries/ecommerce/ecommerce-complete.md +631 -0
- package/industries/education/education-complete.md +555 -0
- package/industries/fintech/fintech-complete.md +501 -0
- package/industries/gaming/gaming-complete.md +587 -0
- package/industries/healthcare/healthcare-complete.md +452 -0
- package/low-code/01-standards/low-code-complete.md +944 -0
- package/miniprogram/01-standards/ai-common-mistakes.md +61 -0
- package/miniprogram/01-standards/miniprogram-custom-navbar-capsule.md +77 -0
- package/miniprogram/01-standards/miniprogram-design.md +61 -0
- package/miniprogram/01-standards/miniprogram-standard.md +81 -0
- package/mobile/01-standards/android-material-design.md +70 -0
- package/mobile/01-standards/flutter-complete.md +384 -0
- package/mobile/01-standards/ios-design-hig.md +78 -0
- package/mobile/01-standards/mobile-app-standard.md +85 -0
- package/mobile/01-standards/react-native-complete.md +352 -0
- package/mobile/02-playbooks/mobile-cross-platform-playbook.md +175 -0
- package/mobile/02-playbooks/mobile-performance.md +473 -0
- package/mobile/03-checklists/mobile-release-checklist.md +234 -0
- package/mobile/04-antipatterns/mobile-antipatterns.md +798 -0
- package/mobile/05-cases/case-app-performance.md +500 -0
- package/mobile/05-cases/case-app-startup-optimization.md +218 -0
- package/mobile/06-glossary/mobile-glossary.md +484 -0
- package/observability/01-standards/observability-standards.md +103 -0
- package/observability/02-playbooks/prometheus-grafana-playbook.md +135 -0
- package/observability/02-playbooks/structured-logging-playbook.md +73 -0
- package/observability/03-checklists/observability-checklist.md +54 -0
- package/observability/04-antipatterns/observability-antipatterns.md +106 -0
- package/operations/01-standards/prometheus-monitoring-complete.md +1578 -0
- package/operations/02-playbooks/capacity-planning-playbook.md +620 -0
- package/operations/03-checklists/production-launch-checklist.md +365 -0
- package/operations/04-antipatterns/operations-antipatterns.md +664 -0
- package/operations/05-cases/case-sre-practices.md +581 -0
- package/operations/06-glossary/operations-glossary.md +120 -0
- package/operations/aiops-anomaly-detection.md +758 -0
- package/operations/capacity-planning.md +1061 -0
- package/operations/chaos-engineering.md +659 -0
- package/operations/incident-command-system.md +38 -0
- package/operations/observability-complete.md +442 -0
- package/operations/slo-sli-playbook.md +517 -0
- package/operations/sre-operations-deep-dive.md +39 -0
- package/package.json +8 -0
- package/performance/01-standards/performance-and-scalability.md +80 -0
- package/performance/01-standards/performance-standards.md +156 -0
- package/performance/02-playbooks/query-optimization-playbook.md +103 -0
- package/performance/03-checklists/performance-checklist.md +56 -0
- package/performance/04-antipatterns/performance-antipatterns.md +146 -0
- package/product/01-standards/product-management-complete.md +285 -0
- package/product/02-playbooks/feature-launch-playbook.md +207 -0
- package/product/02-playbooks/user-research-playbook.md +532 -0
- package/product/03-checklists/feature-launch-checklist.md +275 -0
- package/product/04-antipatterns/product-antipatterns.md +355 -0
- package/product/05-cases/case-mvp-to-scale.md +384 -0
- package/product/06-glossary/product-glossary.md +462 -0
- package/product/feature-prioritization-framework.md +40 -0
- package/product/kpi-and-metric-tree.md +37 -0
- package/product/product-discovery-and-prd-deep-dive.md +41 -0
- package/quantum/01-standards/quantum-complete.md +1186 -0
- package/security/01-standards/api-security-complete.md +511 -0
- package/security/01-standards/container-runtime-security.md +574 -0
- package/security/01-standards/data-protection-gdpr.md +543 -0
- package/security/01-standards/owasp-top10-complete.md +1890 -0
- package/security/01-standards/secure-coding-baseline.md +90 -0
- package/security/01-standards/supply-chain-security.md +441 -0
- package/security/01-standards/web-security-checklist.md +108 -0
- package/security/01-standards/zero-trust-architecture.md +521 -0
- package/security/02-playbooks/auth-sso-playbook.md +166 -0
- package/security/02-playbooks/incident-response-security-playbook.md +588 -0
- package/security/02-playbooks/owasp-api-security-playbook.md +129 -0
- package/security/02-playbooks/payment-integration-playbook.md +119 -0
- package/security/02-playbooks/penetration-testing-playbook.md +517 -0
- package/security/03-checklists/security-audit-checklist.md +356 -0
- package/security/04-antipatterns/security-coding-antipatterns.md +580 -0
- package/security/05-cases/case-log4shell-incident.md +537 -0
- package/security/05-cases/case-major-breaches.md +468 -0
- package/security/06-glossary/security-glossary.md +212 -0
- package/security/compliance-automation.md +993 -0
- package/security/container-security.md +680 -0
- package/security/devsecops-complete.md +426 -0
- package/security/sast-dast-sca.md +775 -0
- package/security/secrets-management.md +594 -0
- package/security/security-architecture-deep-dive.md +37 -0
- package/security/threat-modeling-stride-playbook.md +40 -0
- package/seed-templates/auth-system.md +59 -0
- package/seed-templates/blog-content.md +94 -0
- package/seed-templates/dashboard.md +89 -0
- package/seed-templates/docs-site.md +73 -0
- package/seed-templates/e-commerce.md +50 -0
- package/seed-templates/saas-landing.md +92 -0
- package/seed-templates/settings-page.md +51 -0
- package/testing/01-standards/test-strategy-and-layering.md +83 -0
- package/testing/01-standards/testing-strategy-complete.md +422 -0
- package/testing/01-standards/unit-testing-best-practices.md +118 -0
- package/testing/02-playbooks/e2e-testing-playbook.md +988 -0
- package/testing/02-playbooks/testing-strategy-playbook.md +126 -0
- package/testing/03-checklists/test-strategy-checklist.md +208 -0
- package/testing/04-antipatterns/testing-antipatterns.md +718 -0
- package/testing/05-cases/case-testing-transformation.md +300 -0
- package/testing/06-glossary/testing-glossary.md +110 -0
- package/testing/risk-based-test-matrix.md +36 -0
- package/testing/testing-strategy-deep-dive.md +37 -0
|
@@ -0,0 +1,1613 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: postgresql-complete
|
|
3
|
+
title: PostgreSQL 数据工程完整指南
|
|
4
|
+
domain: data
|
|
5
|
+
category: 01-standards
|
|
6
|
+
difficulty: intermediate
|
|
7
|
+
tags: [complete, data, postgresql, 备份与恢复, 安全, 数据建模, 查询优化, 核心概念]
|
|
8
|
+
quality_score: 70
|
|
9
|
+
last_updated: 2026-06-15
|
|
10
|
+
---
|
|
11
|
+
# PostgreSQL 数据工程完整指南
|
|
12
|
+
|
|
13
|
+
> 文档版本: v1.0 | 最后更新: 2026-03-28 | 适用范围: PostgreSQL 14-17
|
|
14
|
+
|
|
15
|
+
## 1. 概述
|
|
16
|
+
|
|
17
|
+
PostgreSQL 是世界上最先进的开源关系型数据库管理系统,具备 ACID 完全合规、MVCC 并发控制、可扩展类型系统和丰富的索引能力。在数据工程场景中,PostgreSQL 承担 OLTP 核心存储、数据仓库辅助层、实时分析和 JSON 文档存储等多重角色。
|
|
18
|
+
|
|
19
|
+
### 1.1 适用场景
|
|
20
|
+
|
|
21
|
+
| 场景 | 推荐度 | 说明 |
|
|
22
|
+
|------|--------|------|
|
|
23
|
+
| OLTP 业务系统 | ★★★★★ | 事务完整性、行级锁、外键约束 |
|
|
24
|
+
| JSONB 文档存储 | ★★★★☆ | 替代部分 MongoDB 场景 |
|
|
25
|
+
| 地理信息系统 | ★★★★★ | PostGIS 扩展 |
|
|
26
|
+
| 全文搜索 | ★★★★☆ | tsvector/tsquery,中小规模可替代 ES |
|
|
27
|
+
| 大规模 OLAP | ★★★☆☆ | 需配合 Citus / TimescaleDB 或分区表 |
|
|
28
|
+
| 时序数据 | ★★★★☆ | TimescaleDB 扩展 |
|
|
29
|
+
|
|
30
|
+
### 1.2 版本选择
|
|
31
|
+
|
|
32
|
+
```sql
|
|
33
|
+
-- 查看当前版本
|
|
34
|
+
SELECT version();
|
|
35
|
+
|
|
36
|
+
-- 推荐版本:
|
|
37
|
+
-- 生产环境: PostgreSQL 16 (当前稳定长期支持)
|
|
38
|
+
-- 新项目: PostgreSQL 17 (最新特性)
|
|
39
|
+
-- 遗留系统: PostgreSQL 14+ (最低安全维护线)
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## 2. 核心概念
|
|
45
|
+
|
|
46
|
+
### 2.1 MVCC (多版本并发控制)
|
|
47
|
+
|
|
48
|
+
PostgreSQL 通过 MVCC 实现读写不阻塞。每行数据包含 `xmin`(创建事务ID)和 `xmax`(删除事务ID)两个隐藏列,事务根据快照可见性判断数据是否可见。
|
|
49
|
+
|
|
50
|
+
```sql
|
|
51
|
+
-- 查看行的 MVCC 元信息
|
|
52
|
+
SELECT xmin, xmax, ctid, * FROM orders LIMIT 5;
|
|
53
|
+
|
|
54
|
+
-- ctid 是行的物理位置 (页号, 行号)
|
|
55
|
+
-- xmin 是插入该行的事务ID
|
|
56
|
+
-- xmax 是删除/更新该行的事务ID (0 表示未被删除)
|
|
57
|
+
|
|
58
|
+
-- 模拟 MVCC 行为
|
|
59
|
+
BEGIN;
|
|
60
|
+
UPDATE accounts SET balance = balance - 100 WHERE id = 1;
|
|
61
|
+
-- 此时旧版本仍对其他事务可见
|
|
62
|
+
-- 新版本仅对当前事务可见
|
|
63
|
+
COMMIT;
|
|
64
|
+
-- 提交后,旧版本标记为可回收,新版本对所有后续事务可见
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
**MVCC 的代价 -- 膨胀 (Bloat):**
|
|
68
|
+
|
|
69
|
+
```sql
|
|
70
|
+
-- 死元组积累导致表膨胀,需要 VACUUM 回收空间
|
|
71
|
+
-- 查看表的死元组数量
|
|
72
|
+
SELECT relname, n_dead_tup, n_live_tup,
|
|
73
|
+
round(n_dead_tup::numeric / GREATEST(n_live_tup, 1) * 100, 2) AS dead_ratio_pct
|
|
74
|
+
FROM pg_stat_user_tables
|
|
75
|
+
WHERE n_dead_tup > 1000
|
|
76
|
+
ORDER BY n_dead_tup DESC;
|
|
77
|
+
|
|
78
|
+
-- 手动触发 VACUUM
|
|
79
|
+
VACUUM VERBOSE orders;
|
|
80
|
+
|
|
81
|
+
-- VACUUM FULL 会重写整张表(锁表,慎用)
|
|
82
|
+
VACUUM FULL orders;
|
|
83
|
+
|
|
84
|
+
-- 推荐: 调优 autovacuum 参数而非手动执行
|
|
85
|
+
ALTER TABLE orders SET (
|
|
86
|
+
autovacuum_vacuum_threshold = 50,
|
|
87
|
+
autovacuum_vacuum_scale_factor = 0.05, -- 5% 死元组即触发
|
|
88
|
+
autovacuum_analyze_threshold = 50,
|
|
89
|
+
autovacuum_analyze_scale_factor = 0.02
|
|
90
|
+
);
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### 2.2 WAL (预写日志)
|
|
94
|
+
|
|
95
|
+
WAL 是 PostgreSQL 持久性的基石。所有数据修改先写入 WAL,再异步刷入数据文件,确保崩溃后可完整恢复。
|
|
96
|
+
|
|
97
|
+
```sql
|
|
98
|
+
-- 查看当前 WAL 位置
|
|
99
|
+
SELECT pg_current_wal_lsn(), pg_current_wal_insert_lsn();
|
|
100
|
+
|
|
101
|
+
-- 查看 WAL 文件大小设置
|
|
102
|
+
SHOW wal_segment_size; -- 默认 16MB
|
|
103
|
+
|
|
104
|
+
-- 查看 WAL 级别
|
|
105
|
+
SHOW wal_level; -- minimal / replica / logical
|
|
106
|
+
|
|
107
|
+
-- 生产环境必须设为 replica 或 logical
|
|
108
|
+
-- postgresql.conf
|
|
109
|
+
-- wal_level = replica # 支持物理复制
|
|
110
|
+
-- wal_level = logical # 支持逻辑复制 + CDC
|
|
111
|
+
|
|
112
|
+
-- 查看 WAL 写入统计
|
|
113
|
+
SELECT * FROM pg_stat_wal;
|
|
114
|
+
|
|
115
|
+
-- 查看 WAL 归档状态
|
|
116
|
+
SELECT * FROM pg_stat_archiver;
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
### 2.3 事务隔离级别
|
|
120
|
+
|
|
121
|
+
PostgreSQL 支持四种 SQL 标准隔离级别,实际实现三种(READ UNCOMMITTED 等同 READ COMMITTED)。
|
|
122
|
+
|
|
123
|
+
```sql
|
|
124
|
+
-- 查看当前隔离级别
|
|
125
|
+
SHOW transaction_isolation; -- 默认 read committed
|
|
126
|
+
|
|
127
|
+
-- 设置会话级隔离
|
|
128
|
+
SET SESSION CHARACTERISTICS AS TRANSACTION ISOLATION LEVEL REPEATABLE READ;
|
|
129
|
+
|
|
130
|
+
-- 设置单事务隔离
|
|
131
|
+
BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE;
|
|
132
|
+
-- 最严格:可序列化,防止所有异常
|
|
133
|
+
-- 但性能开销最大,可能触发序列化失败需重试
|
|
134
|
+
SELECT * FROM inventory WHERE product_id = 42 FOR UPDATE;
|
|
135
|
+
UPDATE inventory SET quantity = quantity - 1 WHERE product_id = 42;
|
|
136
|
+
COMMIT;
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
**各隔离级别对比:**
|
|
140
|
+
|
|
141
|
+
| 隔离级别 | 脏读 | 不可重复读 | 幻读 | 序列化异常 | 适用场景 |
|
|
142
|
+
|----------|------|-----------|------|-----------|---------|
|
|
143
|
+
| READ COMMITTED | 否 | 可能 | 可能 | 可能 | 默认,大多数 OLTP |
|
|
144
|
+
| REPEATABLE READ | 否 | 否 | 否* | 可能 | 报表、一致性快照 |
|
|
145
|
+
| SERIALIZABLE | 否 | 否 | 否 | 否 | 金融、库存扣减 |
|
|
146
|
+
|
|
147
|
+
> *PostgreSQL 的 REPEATABLE READ 通过快照隔离同时防止了幻读。
|
|
148
|
+
|
|
149
|
+
```sql
|
|
150
|
+
-- 序列化失败重试模式(应用层必须实现)
|
|
151
|
+
-- Python 伪代码:
|
|
152
|
+
-- for attempt in range(MAX_RETRIES):
|
|
153
|
+
-- try:
|
|
154
|
+
-- with conn.cursor() as cur:
|
|
155
|
+
-- cur.execute("BEGIN ISOLATION LEVEL SERIALIZABLE")
|
|
156
|
+
-- cur.execute("SELECT ... FOR UPDATE")
|
|
157
|
+
-- cur.execute("UPDATE ...")
|
|
158
|
+
-- cur.execute("COMMIT")
|
|
159
|
+
-- break
|
|
160
|
+
-- except psycopg2.errors.SerializationFailure:
|
|
161
|
+
-- conn.rollback()
|
|
162
|
+
-- continue
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
### 2.4 锁机制
|
|
166
|
+
|
|
167
|
+
```sql
|
|
168
|
+
-- 查看当前锁等待
|
|
169
|
+
SELECT blocked_locks.pid AS blocked_pid,
|
|
170
|
+
blocked_activity.usename AS blocked_user,
|
|
171
|
+
blocking_locks.pid AS blocking_pid,
|
|
172
|
+
blocking_activity.usename AS blocking_user,
|
|
173
|
+
blocked_activity.query AS blocked_statement,
|
|
174
|
+
blocking_activity.query AS current_statement_in_blocking_process
|
|
175
|
+
FROM pg_catalog.pg_locks blocked_locks
|
|
176
|
+
JOIN pg_catalog.pg_stat_activity blocked_activity
|
|
177
|
+
ON blocked_activity.pid = blocked_locks.pid
|
|
178
|
+
JOIN pg_catalog.pg_locks blocking_locks
|
|
179
|
+
ON blocking_locks.locktype = blocked_locks.locktype
|
|
180
|
+
AND blocking_locks.database IS NOT DISTINCT FROM blocked_locks.database
|
|
181
|
+
AND blocking_locks.relation IS NOT DISTINCT FROM blocked_locks.relation
|
|
182
|
+
AND blocking_locks.page IS NOT DISTINCT FROM blocked_locks.page
|
|
183
|
+
AND blocking_locks.tuple IS NOT DISTINCT FROM blocked_locks.tuple
|
|
184
|
+
AND blocking_locks.virtualxid IS NOT DISTINCT FROM blocked_locks.virtualxid
|
|
185
|
+
AND blocking_locks.transactionid IS NOT DISTINCT FROM blocked_locks.transactionid
|
|
186
|
+
AND blocking_locks.classid IS NOT DISTINCT FROM blocked_locks.classid
|
|
187
|
+
AND blocking_locks.objid IS NOT DISTINCT FROM blocked_locks.objid
|
|
188
|
+
AND blocking_locks.objsubid IS NOT DISTINCT FROM blocked_locks.objsubid
|
|
189
|
+
AND blocking_locks.pid != blocked_locks.pid
|
|
190
|
+
JOIN pg_catalog.pg_stat_activity blocking_activity
|
|
191
|
+
ON blocking_activity.pid = blocking_locks.pid
|
|
192
|
+
WHERE NOT blocked_locks.granted;
|
|
193
|
+
|
|
194
|
+
-- 设置锁超时(避免无限等待)
|
|
195
|
+
SET lock_timeout = '5s';
|
|
196
|
+
|
|
197
|
+
-- 使用 advisory lock 实现应用级互斥
|
|
198
|
+
SELECT pg_advisory_lock(hashtext('order_processing'));
|
|
199
|
+
-- ... 执行业务逻辑 ...
|
|
200
|
+
SELECT pg_advisory_unlock(hashtext('order_processing'));
|
|
201
|
+
|
|
202
|
+
-- 非阻塞方式
|
|
203
|
+
SELECT pg_try_advisory_lock(hashtext('order_processing'));
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
---
|
|
207
|
+
|
|
208
|
+
## 3. 数据建模
|
|
209
|
+
|
|
210
|
+
### 3.1 范式化设计 (3NF)
|
|
211
|
+
|
|
212
|
+
```sql
|
|
213
|
+
-- 规范的三范式设计
|
|
214
|
+
CREATE TABLE customers (
|
|
215
|
+
id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
|
|
216
|
+
email VARCHAR(255) UNIQUE NOT NULL,
|
|
217
|
+
name VARCHAR(100) NOT NULL,
|
|
218
|
+
phone VARCHAR(20),
|
|
219
|
+
created_at TIMESTAMPTZ DEFAULT now()
|
|
220
|
+
);
|
|
221
|
+
|
|
222
|
+
CREATE TABLE addresses (
|
|
223
|
+
id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
|
|
224
|
+
customer_id BIGINT NOT NULL REFERENCES customers(id) ON DELETE CASCADE,
|
|
225
|
+
type VARCHAR(20) NOT NULL CHECK (type IN ('billing', 'shipping')),
|
|
226
|
+
line1 VARCHAR(255) NOT NULL,
|
|
227
|
+
line2 VARCHAR(255),
|
|
228
|
+
city VARCHAR(100) NOT NULL,
|
|
229
|
+
state VARCHAR(50),
|
|
230
|
+
postal_code VARCHAR(20) NOT NULL,
|
|
231
|
+
country CHAR(2) NOT NULL, -- ISO 3166-1 alpha-2
|
|
232
|
+
UNIQUE (customer_id, type)
|
|
233
|
+
);
|
|
234
|
+
|
|
235
|
+
CREATE TABLE orders (
|
|
236
|
+
id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
|
|
237
|
+
customer_id BIGINT NOT NULL REFERENCES customers(id),
|
|
238
|
+
address_id BIGINT NOT NULL REFERENCES addresses(id),
|
|
239
|
+
status VARCHAR(20) NOT NULL DEFAULT 'pending'
|
|
240
|
+
CHECK (status IN ('pending','confirmed','shipped','delivered','cancelled')),
|
|
241
|
+
total NUMERIC(12, 2) NOT NULL CHECK (total >= 0),
|
|
242
|
+
ordered_at TIMESTAMPTZ DEFAULT now()
|
|
243
|
+
);
|
|
244
|
+
|
|
245
|
+
CREATE TABLE order_items (
|
|
246
|
+
id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
|
|
247
|
+
order_id BIGINT NOT NULL REFERENCES orders(id) ON DELETE CASCADE,
|
|
248
|
+
product_id BIGINT NOT NULL,
|
|
249
|
+
quantity INTEGER NOT NULL CHECK (quantity > 0),
|
|
250
|
+
unit_price NUMERIC(10, 2) NOT NULL CHECK (unit_price >= 0),
|
|
251
|
+
subtotal NUMERIC(12, 2) GENERATED ALWAYS AS (quantity * unit_price) STORED
|
|
252
|
+
);
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
### 3.2 反范式化设计
|
|
256
|
+
|
|
257
|
+
```sql
|
|
258
|
+
-- 为读密集场景添加冗余字段
|
|
259
|
+
ALTER TABLE orders ADD COLUMN customer_name VARCHAR(100);
|
|
260
|
+
ALTER TABLE orders ADD COLUMN item_count INTEGER DEFAULT 0;
|
|
261
|
+
|
|
262
|
+
-- 使用触发器维护冗余数据一致性
|
|
263
|
+
CREATE OR REPLACE FUNCTION update_order_item_count()
|
|
264
|
+
RETURNS TRIGGER AS $$
|
|
265
|
+
BEGIN
|
|
266
|
+
IF TG_OP = 'INSERT' THEN
|
|
267
|
+
UPDATE orders SET item_count = item_count + 1 WHERE id = NEW.order_id;
|
|
268
|
+
ELSIF TG_OP = 'DELETE' THEN
|
|
269
|
+
UPDATE orders SET item_count = item_count - 1 WHERE id = OLD.order_id;
|
|
270
|
+
END IF;
|
|
271
|
+
RETURN NULL;
|
|
272
|
+
END;
|
|
273
|
+
$$ LANGUAGE plpgsql;
|
|
274
|
+
|
|
275
|
+
CREATE TRIGGER trg_order_item_count
|
|
276
|
+
AFTER INSERT OR DELETE ON order_items
|
|
277
|
+
FOR EACH ROW EXECUTE FUNCTION update_order_item_count();
|
|
278
|
+
|
|
279
|
+
-- 物化视图用于重聚合场景
|
|
280
|
+
CREATE MATERIALIZED VIEW mv_daily_sales AS
|
|
281
|
+
SELECT
|
|
282
|
+
date_trunc('day', o.ordered_at)::DATE AS sale_date,
|
|
283
|
+
count(DISTINCT o.id) AS order_count,
|
|
284
|
+
sum(o.total) AS revenue,
|
|
285
|
+
count(DISTINCT o.customer_id) AS unique_customers
|
|
286
|
+
FROM orders o
|
|
287
|
+
WHERE o.status != 'cancelled'
|
|
288
|
+
GROUP BY 1;
|
|
289
|
+
|
|
290
|
+
CREATE UNIQUE INDEX idx_mv_daily_sales_date ON mv_daily_sales(sale_date);
|
|
291
|
+
|
|
292
|
+
-- 定时刷新(配合 pg_cron 或外部调度)
|
|
293
|
+
REFRESH MATERIALIZED VIEW CONCURRENTLY mv_daily_sales;
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
### 3.3 JSONB 混合建模
|
|
297
|
+
|
|
298
|
+
```sql
|
|
299
|
+
-- 结构化 + 半结构化混合
|
|
300
|
+
CREATE TABLE products (
|
|
301
|
+
id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
|
|
302
|
+
sku VARCHAR(50) UNIQUE NOT NULL,
|
|
303
|
+
name VARCHAR(255) NOT NULL,
|
|
304
|
+
category VARCHAR(100) NOT NULL,
|
|
305
|
+
price NUMERIC(10, 2) NOT NULL,
|
|
306
|
+
-- 半结构化属性 (颜色、尺寸、规格等因品类而异)
|
|
307
|
+
attributes JSONB NOT NULL DEFAULT '{}',
|
|
308
|
+
tags TEXT[] DEFAULT '{}',
|
|
309
|
+
created_at TIMESTAMPTZ DEFAULT now()
|
|
310
|
+
);
|
|
311
|
+
|
|
312
|
+
-- JSONB 查询示例
|
|
313
|
+
-- 查找红色产品
|
|
314
|
+
SELECT * FROM products
|
|
315
|
+
WHERE attributes @> '{"color": "red"}';
|
|
316
|
+
|
|
317
|
+
-- 查找包含特定嵌套属性的产品
|
|
318
|
+
SELECT * FROM products
|
|
319
|
+
WHERE attributes -> 'specs' ->> 'weight_kg' IS NOT NULL
|
|
320
|
+
AND (attributes -> 'specs' ->> 'weight_kg')::numeric < 5.0;
|
|
321
|
+
|
|
322
|
+
-- JSONB 聚合
|
|
323
|
+
SELECT
|
|
324
|
+
attributes ->> 'brand' AS brand,
|
|
325
|
+
count(*) AS product_count,
|
|
326
|
+
avg(price) AS avg_price
|
|
327
|
+
FROM products
|
|
328
|
+
WHERE attributes ? 'brand'
|
|
329
|
+
GROUP BY attributes ->> 'brand'
|
|
330
|
+
ORDER BY product_count DESC;
|
|
331
|
+
|
|
332
|
+
-- 更新 JSONB 字段
|
|
333
|
+
UPDATE products
|
|
334
|
+
SET attributes = jsonb_set(
|
|
335
|
+
attributes,
|
|
336
|
+
'{specs, weight_kg}',
|
|
337
|
+
'2.5'::jsonb
|
|
338
|
+
)
|
|
339
|
+
WHERE sku = 'PROD-001';
|
|
340
|
+
|
|
341
|
+
-- 删除 JSONB 中的键
|
|
342
|
+
UPDATE products
|
|
343
|
+
SET attributes = attributes - 'deprecated_field'
|
|
344
|
+
WHERE attributes ? 'deprecated_field';
|
|
345
|
+
|
|
346
|
+
-- 生成列基于 JSONB(PostgreSQL 12+)
|
|
347
|
+
ALTER TABLE products ADD COLUMN brand VARCHAR(100)
|
|
348
|
+
GENERATED ALWAYS AS (attributes ->> 'brand') STORED;
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
---
|
|
352
|
+
|
|
353
|
+
## 4. 索引策略
|
|
354
|
+
|
|
355
|
+
### 4.1 B-tree 索引(默认)
|
|
356
|
+
|
|
357
|
+
```sql
|
|
358
|
+
-- 最常用,适合等值和范围查询
|
|
359
|
+
CREATE INDEX idx_orders_customer ON orders(customer_id);
|
|
360
|
+
CREATE INDEX idx_orders_status_date ON orders(status, ordered_at DESC);
|
|
361
|
+
|
|
362
|
+
-- 验证索引是否被使用
|
|
363
|
+
EXPLAIN (ANALYZE, BUFFERS, FORMAT TEXT)
|
|
364
|
+
SELECT * FROM orders WHERE customer_id = 42 AND status = 'shipped';
|
|
365
|
+
```
|
|
366
|
+
|
|
367
|
+
### 4.2 GIN 索引(通用倒排)
|
|
368
|
+
|
|
369
|
+
```sql
|
|
370
|
+
-- JSONB 查询加速
|
|
371
|
+
CREATE INDEX idx_products_attrs ON products USING GIN (attributes);
|
|
372
|
+
CREATE INDEX idx_products_attrs_path ON products USING GIN (attributes jsonb_path_ops);
|
|
373
|
+
-- jsonb_path_ops 更小更快,但仅支持 @> 操作符
|
|
374
|
+
|
|
375
|
+
-- 数组查询加速
|
|
376
|
+
CREATE INDEX idx_products_tags ON products USING GIN (tags);
|
|
377
|
+
|
|
378
|
+
-- 全文搜索
|
|
379
|
+
ALTER TABLE products ADD COLUMN search_vector tsvector
|
|
380
|
+
GENERATED ALWAYS AS (
|
|
381
|
+
setweight(to_tsvector('simple', coalesce(name, '')), 'A') ||
|
|
382
|
+
setweight(to_tsvector('simple', coalesce(category, '')), 'B')
|
|
383
|
+
) STORED;
|
|
384
|
+
CREATE INDEX idx_products_search ON products USING GIN (search_vector);
|
|
385
|
+
|
|
386
|
+
-- 全文搜索查询
|
|
387
|
+
SELECT name, ts_rank(search_vector, query) AS rank
|
|
388
|
+
FROM products, to_tsquery('simple', '无线 & 耳机') AS query
|
|
389
|
+
WHERE search_vector @@ query
|
|
390
|
+
ORDER BY rank DESC;
|
|
391
|
+
```
|
|
392
|
+
|
|
393
|
+
### 4.3 GiST 索引(通用搜索树)
|
|
394
|
+
|
|
395
|
+
```sql
|
|
396
|
+
-- 范围类型查询
|
|
397
|
+
CREATE TABLE reservations (
|
|
398
|
+
id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
|
|
399
|
+
room_id INTEGER NOT NULL,
|
|
400
|
+
period TSTZRANGE NOT NULL,
|
|
401
|
+
EXCLUDE USING GIST (room_id WITH =, period WITH &&)
|
|
402
|
+
-- 排他约束: 同一房间不允许时间重叠
|
|
403
|
+
);
|
|
404
|
+
|
|
405
|
+
-- 地理空间查询 (需要 PostGIS)
|
|
406
|
+
-- CREATE INDEX idx_locations_geom ON locations USING GIST (geom);
|
|
407
|
+
-- SELECT * FROM locations WHERE ST_DWithin(geom, ST_MakePoint(116.4, 39.9)::geography, 1000);
|
|
408
|
+
|
|
409
|
+
-- 最近邻搜索
|
|
410
|
+
CREATE TABLE points (id serial, coords point);
|
|
411
|
+
CREATE INDEX idx_points_coords ON points USING GIST (coords);
|
|
412
|
+
SELECT * FROM points ORDER BY coords <-> point '(3,4)' LIMIT 10;
|
|
413
|
+
```
|
|
414
|
+
|
|
415
|
+
### 4.4 BRIN 索引(块范围索引)
|
|
416
|
+
|
|
417
|
+
```sql
|
|
418
|
+
-- 适合物理有序的大表 (时序数据、日志表)
|
|
419
|
+
-- 体积极小 (B-tree 的 1/100),扫描时跳过不相关的块
|
|
420
|
+
CREATE TABLE event_logs (
|
|
421
|
+
id BIGINT GENERATED ALWAYS AS IDENTITY,
|
|
422
|
+
event_time TIMESTAMPTZ NOT NULL DEFAULT now(),
|
|
423
|
+
event_type VARCHAR(50),
|
|
424
|
+
payload JSONB
|
|
425
|
+
);
|
|
426
|
+
|
|
427
|
+
CREATE INDEX idx_logs_time_brin ON event_logs USING BRIN (event_time)
|
|
428
|
+
WITH (pages_per_range = 32);
|
|
429
|
+
|
|
430
|
+
-- 查询只扫描相关块
|
|
431
|
+
EXPLAIN ANALYZE
|
|
432
|
+
SELECT * FROM event_logs
|
|
433
|
+
WHERE event_time BETWEEN '2026-03-01' AND '2026-03-28';
|
|
434
|
+
```
|
|
435
|
+
|
|
436
|
+
### 4.5 部分索引
|
|
437
|
+
|
|
438
|
+
```sql
|
|
439
|
+
-- 只索引活跃数据,减小索引体积
|
|
440
|
+
CREATE INDEX idx_orders_active ON orders(customer_id, ordered_at)
|
|
441
|
+
WHERE status NOT IN ('cancelled', 'delivered');
|
|
442
|
+
|
|
443
|
+
-- 唯一性约束仅对活跃记录生效
|
|
444
|
+
CREATE UNIQUE INDEX idx_users_active_email ON users(email)
|
|
445
|
+
WHERE deleted_at IS NULL;
|
|
446
|
+
```
|
|
447
|
+
|
|
448
|
+
### 4.6 覆盖索引 (INCLUDE)
|
|
449
|
+
|
|
450
|
+
```sql
|
|
451
|
+
-- 索引包含额外列,避免回表 (Index-Only Scan)
|
|
452
|
+
CREATE INDEX idx_orders_covering ON orders(customer_id, ordered_at DESC)
|
|
453
|
+
INCLUDE (status, total);
|
|
454
|
+
|
|
455
|
+
-- 此查询可完全从索引中获取数据
|
|
456
|
+
EXPLAIN ANALYZE
|
|
457
|
+
SELECT customer_id, ordered_at, status, total
|
|
458
|
+
FROM orders
|
|
459
|
+
WHERE customer_id = 42
|
|
460
|
+
ORDER BY ordered_at DESC
|
|
461
|
+
LIMIT 20;
|
|
462
|
+
```
|
|
463
|
+
|
|
464
|
+
### 4.7 索引维护
|
|
465
|
+
|
|
466
|
+
```sql
|
|
467
|
+
-- 查看索引大小和使用情况
|
|
468
|
+
SELECT
|
|
469
|
+
schemaname, tablename, indexname,
|
|
470
|
+
pg_size_pretty(pg_relation_size(indexrelid)) AS index_size,
|
|
471
|
+
idx_scan AS times_used,
|
|
472
|
+
idx_tup_read,
|
|
473
|
+
idx_tup_fetch
|
|
474
|
+
FROM pg_stat_user_indexes
|
|
475
|
+
ORDER BY pg_relation_size(indexrelid) DESC;
|
|
476
|
+
|
|
477
|
+
-- 找出未使用的索引 (运行一段时间后检查)
|
|
478
|
+
SELECT indexrelid::regclass AS index_name,
|
|
479
|
+
relid::regclass AS table_name,
|
|
480
|
+
pg_size_pretty(pg_relation_size(indexrelid)) AS size
|
|
481
|
+
FROM pg_stat_user_indexes
|
|
482
|
+
WHERE idx_scan = 0
|
|
483
|
+
AND indexrelid NOT IN (
|
|
484
|
+
SELECT conindid FROM pg_constraint WHERE contype IN ('p', 'u')
|
|
485
|
+
)
|
|
486
|
+
ORDER BY pg_relation_size(indexrelid) DESC;
|
|
487
|
+
|
|
488
|
+
-- 在线重建索引 (不锁表)
|
|
489
|
+
REINDEX INDEX CONCURRENTLY idx_orders_customer;
|
|
490
|
+
```
|
|
491
|
+
|
|
492
|
+
---
|
|
493
|
+
|
|
494
|
+
## 5. 查询优化
|
|
495
|
+
|
|
496
|
+
### 5.1 EXPLAIN ANALYZE 深度解读
|
|
497
|
+
|
|
498
|
+
```sql
|
|
499
|
+
-- 基本用法
|
|
500
|
+
EXPLAIN (ANALYZE, BUFFERS, COSTS, TIMING, FORMAT TEXT)
|
|
501
|
+
SELECT o.id, o.total, c.name
|
|
502
|
+
FROM orders o
|
|
503
|
+
JOIN customers c ON c.id = o.customer_id
|
|
504
|
+
WHERE o.ordered_at >= '2026-01-01'
|
|
505
|
+
AND o.status = 'shipped'
|
|
506
|
+
ORDER BY o.ordered_at DESC
|
|
507
|
+
LIMIT 50;
|
|
508
|
+
|
|
509
|
+
-- 关键指标解读:
|
|
510
|
+
-- actual time: 首行返回时间..最后行返回时间 (毫秒)
|
|
511
|
+
-- rows: 实际返回行数 (对比 Plan rows 判断统计信息准确性)
|
|
512
|
+
-- Buffers: shared hit (缓存命中) / shared read (磁盘读)
|
|
513
|
+
-- 理想情况: hit >> read
|
|
514
|
+
|
|
515
|
+
-- 强制更新统计信息
|
|
516
|
+
ANALYZE orders;
|
|
517
|
+
ANALYZE customers;
|
|
518
|
+
|
|
519
|
+
-- 查看表级统计
|
|
520
|
+
SELECT attname, n_distinct, most_common_vals, histogram_bounds
|
|
521
|
+
FROM pg_stats
|
|
522
|
+
WHERE tablename = 'orders' AND attname = 'status';
|
|
523
|
+
```
|
|
524
|
+
|
|
525
|
+
### 5.2 CTE (公用表表达式)
|
|
526
|
+
|
|
527
|
+
```sql
|
|
528
|
+
-- 可读性优先的复杂查询拆解
|
|
529
|
+
WITH monthly_revenue AS (
|
|
530
|
+
SELECT
|
|
531
|
+
date_trunc('month', ordered_at)::DATE AS month,
|
|
532
|
+
sum(total) AS revenue,
|
|
533
|
+
count(*) AS order_count
|
|
534
|
+
FROM orders
|
|
535
|
+
WHERE status != 'cancelled'
|
|
536
|
+
AND ordered_at >= '2025-01-01'
|
|
537
|
+
GROUP BY 1
|
|
538
|
+
),
|
|
539
|
+
growth AS (
|
|
540
|
+
SELECT
|
|
541
|
+
month,
|
|
542
|
+
revenue,
|
|
543
|
+
order_count,
|
|
544
|
+
lag(revenue) OVER (ORDER BY month) AS prev_revenue,
|
|
545
|
+
round(
|
|
546
|
+
(revenue - lag(revenue) OVER (ORDER BY month))
|
|
547
|
+
/ NULLIF(lag(revenue) OVER (ORDER BY month), 0) * 100, 2
|
|
548
|
+
) AS growth_pct
|
|
549
|
+
FROM monthly_revenue
|
|
550
|
+
)
|
|
551
|
+
SELECT * FROM growth ORDER BY month;
|
|
552
|
+
|
|
553
|
+
-- 递归 CTE: 树形结构遍历
|
|
554
|
+
WITH RECURSIVE category_tree AS (
|
|
555
|
+
-- 锚点: 顶级分类
|
|
556
|
+
SELECT id, name, parent_id, 1 AS depth, name::TEXT AS path
|
|
557
|
+
FROM categories WHERE parent_id IS NULL
|
|
558
|
+
|
|
559
|
+
UNION ALL
|
|
560
|
+
|
|
561
|
+
-- 递归: 子分类
|
|
562
|
+
SELECT c.id, c.name, c.parent_id, ct.depth + 1,
|
|
563
|
+
ct.path || ' > ' || c.name
|
|
564
|
+
FROM categories c
|
|
565
|
+
JOIN category_tree ct ON ct.id = c.parent_id
|
|
566
|
+
WHERE ct.depth < 10 -- 防止无限递归
|
|
567
|
+
)
|
|
568
|
+
SELECT * FROM category_tree ORDER BY path;
|
|
569
|
+
|
|
570
|
+
-- PostgreSQL 12+ CTE 默认非物化 (可被内联优化)
|
|
571
|
+
-- 强制物化: WITH cte AS MATERIALIZED (...)
|
|
572
|
+
-- 强制内联: WITH cte AS NOT MATERIALIZED (...)
|
|
573
|
+
```
|
|
574
|
+
|
|
575
|
+
### 5.3 窗口函数
|
|
576
|
+
|
|
577
|
+
```sql
|
|
578
|
+
-- 排名与分析
|
|
579
|
+
SELECT
|
|
580
|
+
customer_id,
|
|
581
|
+
ordered_at,
|
|
582
|
+
total,
|
|
583
|
+
-- 同组内排名
|
|
584
|
+
row_number() OVER w AS rn,
|
|
585
|
+
rank() OVER w AS rnk,
|
|
586
|
+
dense_rank() OVER w AS dense_rnk,
|
|
587
|
+
-- 累计和
|
|
588
|
+
sum(total) OVER (PARTITION BY customer_id ORDER BY ordered_at) AS running_total,
|
|
589
|
+
-- 移动平均
|
|
590
|
+
avg(total) OVER (
|
|
591
|
+
PARTITION BY customer_id
|
|
592
|
+
ORDER BY ordered_at
|
|
593
|
+
ROWS BETWEEN 2 PRECEDING AND CURRENT ROW
|
|
594
|
+
) AS moving_avg_3,
|
|
595
|
+
-- 首尾值
|
|
596
|
+
first_value(total) OVER w AS first_order_total,
|
|
597
|
+
-- 与前一笔差值
|
|
598
|
+
total - lag(total, 1, 0) OVER w AS diff_from_prev
|
|
599
|
+
FROM orders
|
|
600
|
+
WHERE status != 'cancelled'
|
|
601
|
+
WINDOW w AS (PARTITION BY customer_id ORDER BY ordered_at)
|
|
602
|
+
ORDER BY customer_id, ordered_at;
|
|
603
|
+
|
|
604
|
+
-- Top-N per group (每个客户最近3笔订单)
|
|
605
|
+
SELECT * FROM (
|
|
606
|
+
SELECT *, row_number() OVER (
|
|
607
|
+
PARTITION BY customer_id ORDER BY ordered_at DESC
|
|
608
|
+
) AS rn
|
|
609
|
+
FROM orders
|
|
610
|
+
WHERE status != 'cancelled'
|
|
611
|
+
) sub
|
|
612
|
+
WHERE rn <= 3;
|
|
613
|
+
```
|
|
614
|
+
|
|
615
|
+
### 5.4 分区表
|
|
616
|
+
|
|
617
|
+
```sql
|
|
618
|
+
-- 按时间范围分区 (最常见)
|
|
619
|
+
CREATE TABLE events (
|
|
620
|
+
id BIGINT GENERATED ALWAYS AS IDENTITY,
|
|
621
|
+
event_time TIMESTAMPTZ NOT NULL,
|
|
622
|
+
event_type VARCHAR(50) NOT NULL,
|
|
623
|
+
payload JSONB,
|
|
624
|
+
PRIMARY KEY (id, event_time)
|
|
625
|
+
) PARTITION BY RANGE (event_time);
|
|
626
|
+
|
|
627
|
+
-- 创建月分区
|
|
628
|
+
CREATE TABLE events_2026_01 PARTITION OF events
|
|
629
|
+
FOR VALUES FROM ('2026-01-01') TO ('2026-02-01');
|
|
630
|
+
CREATE TABLE events_2026_02 PARTITION OF events
|
|
631
|
+
FOR VALUES FROM ('2026-02-01') TO ('2026-03-01');
|
|
632
|
+
CREATE TABLE events_2026_03 PARTITION OF events
|
|
633
|
+
FOR VALUES FROM ('2026-03-01') TO ('2026-04-01');
|
|
634
|
+
|
|
635
|
+
-- 默认分区 (兜底)
|
|
636
|
+
CREATE TABLE events_default PARTITION OF events DEFAULT;
|
|
637
|
+
|
|
638
|
+
-- 自动创建未来分区的函数
|
|
639
|
+
CREATE OR REPLACE FUNCTION create_monthly_partition(
|
|
640
|
+
parent_table TEXT,
|
|
641
|
+
target_month DATE
|
|
642
|
+
) RETURNS VOID AS $$
|
|
643
|
+
DECLARE
|
|
644
|
+
partition_name TEXT;
|
|
645
|
+
start_date DATE;
|
|
646
|
+
end_date DATE;
|
|
647
|
+
BEGIN
|
|
648
|
+
start_date := date_trunc('month', target_month);
|
|
649
|
+
end_date := start_date + INTERVAL '1 month';
|
|
650
|
+
partition_name := parent_table || '_' || to_char(start_date, 'YYYY_MM');
|
|
651
|
+
|
|
652
|
+
EXECUTE format(
|
|
653
|
+
'CREATE TABLE IF NOT EXISTS %I PARTITION OF %I FOR VALUES FROM (%L) TO (%L)',
|
|
654
|
+
partition_name, parent_table, start_date, end_date
|
|
655
|
+
);
|
|
656
|
+
END;
|
|
657
|
+
$$ LANGUAGE plpgsql;
|
|
658
|
+
|
|
659
|
+
-- 按列表分区 (多租户场景)
|
|
660
|
+
CREATE TABLE tenant_data (
|
|
661
|
+
id BIGINT GENERATED ALWAYS AS IDENTITY,
|
|
662
|
+
tenant_id INTEGER NOT NULL,
|
|
663
|
+
data JSONB,
|
|
664
|
+
PRIMARY KEY (id, tenant_id)
|
|
665
|
+
) PARTITION BY LIST (tenant_id);
|
|
666
|
+
|
|
667
|
+
CREATE TABLE tenant_data_1 PARTITION OF tenant_data FOR VALUES IN (1);
|
|
668
|
+
CREATE TABLE tenant_data_2 PARTITION OF tenant_data FOR VALUES IN (2);
|
|
669
|
+
|
|
670
|
+
-- 分区裁剪验证
|
|
671
|
+
SET enable_partition_pruning = on; -- 默认开启
|
|
672
|
+
EXPLAIN ANALYZE
|
|
673
|
+
SELECT * FROM events WHERE event_time BETWEEN '2026-03-01' AND '2026-03-28';
|
|
674
|
+
-- 应该只扫描 events_2026_03 分区
|
|
675
|
+
```
|
|
676
|
+
|
|
677
|
+
---
|
|
678
|
+
|
|
679
|
+
## 6. 高可用
|
|
680
|
+
|
|
681
|
+
### 6.1 流复制 (Streaming Replication)
|
|
682
|
+
|
|
683
|
+
```sql
|
|
684
|
+
-- 主库配置 (postgresql.conf)
|
|
685
|
+
-- wal_level = replica
|
|
686
|
+
-- max_wal_senders = 10
|
|
687
|
+
-- wal_keep_size = 1GB
|
|
688
|
+
-- synchronous_standby_names = 'standby1' -- 同步复制
|
|
689
|
+
|
|
690
|
+
-- 主库创建复制用户
|
|
691
|
+
CREATE ROLE replicator WITH REPLICATION LOGIN PASSWORD 'strong_password_here';
|
|
692
|
+
|
|
693
|
+
-- pg_hba.conf 添加
|
|
694
|
+
-- host replication replicator standby_ip/32 scram-sha-256
|
|
695
|
+
```
|
|
696
|
+
|
|
697
|
+
```bash
|
|
698
|
+
# 从库初始化
|
|
699
|
+
pg_basebackup -h primary_host -U replicator -D /var/lib/postgresql/data \
|
|
700
|
+
--wal-method=stream --checkpoint=fast --progress --verbose
|
|
701
|
+
|
|
702
|
+
# 从库配置 (postgresql.conf)
|
|
703
|
+
# primary_conninfo = 'host=primary_host port=5432 user=replicator password=...'
|
|
704
|
+
# hot_standby = on
|
|
705
|
+
```
|
|
706
|
+
|
|
707
|
+
```sql
|
|
708
|
+
-- 监控复制状态(在主库执行)
|
|
709
|
+
SELECT
|
|
710
|
+
client_addr,
|
|
711
|
+
state,
|
|
712
|
+
sent_lsn,
|
|
713
|
+
write_lsn,
|
|
714
|
+
flush_lsn,
|
|
715
|
+
replay_lsn,
|
|
716
|
+
pg_wal_lsn_diff(sent_lsn, replay_lsn) AS replication_lag_bytes,
|
|
717
|
+
sync_state
|
|
718
|
+
FROM pg_stat_replication;
|
|
719
|
+
|
|
720
|
+
-- 监控复制延迟(在从库执行)
|
|
721
|
+
SELECT
|
|
722
|
+
now() - pg_last_xact_replay_timestamp() AS replication_delay,
|
|
723
|
+
pg_is_in_recovery() AS is_standby,
|
|
724
|
+
pg_last_wal_receive_lsn(),
|
|
725
|
+
pg_last_wal_replay_lsn();
|
|
726
|
+
```
|
|
727
|
+
|
|
728
|
+
### 6.2 Patroni 高可用集群
|
|
729
|
+
|
|
730
|
+
```yaml
|
|
731
|
+
# patroni.yml 核心配置
|
|
732
|
+
scope: pg-cluster
|
|
733
|
+
name: node1
|
|
734
|
+
|
|
735
|
+
restapi:
|
|
736
|
+
listen: 0.0.0.0:8008
|
|
737
|
+
connect_address: node1:8008
|
|
738
|
+
|
|
739
|
+
etcd3:
|
|
740
|
+
hosts: etcd1:2379,etcd2:2379,etcd3:2379
|
|
741
|
+
|
|
742
|
+
bootstrap:
|
|
743
|
+
dcs:
|
|
744
|
+
ttl: 30
|
|
745
|
+
loop_wait: 10
|
|
746
|
+
retry_timeout: 10
|
|
747
|
+
maximum_lag_on_failover: 1048576 # 1MB
|
|
748
|
+
postgresql:
|
|
749
|
+
use_pg_rewind: true
|
|
750
|
+
parameters:
|
|
751
|
+
max_connections: 200
|
|
752
|
+
shared_buffers: 4GB
|
|
753
|
+
wal_level: replica
|
|
754
|
+
max_wal_senders: 10
|
|
755
|
+
hot_standby: on
|
|
756
|
+
|
|
757
|
+
postgresql:
|
|
758
|
+
listen: 0.0.0.0:5432
|
|
759
|
+
connect_address: node1:5432
|
|
760
|
+
data_dir: /var/lib/postgresql/data
|
|
761
|
+
authentication:
|
|
762
|
+
superuser:
|
|
763
|
+
username: postgres
|
|
764
|
+
password: "${POSTGRES_PASSWORD}"
|
|
765
|
+
replication:
|
|
766
|
+
username: replicator
|
|
767
|
+
password: "${REPLICATION_PASSWORD}"
|
|
768
|
+
```
|
|
769
|
+
|
|
770
|
+
```bash
|
|
771
|
+
# Patroni 集群状态
|
|
772
|
+
patronictl -c /etc/patroni.yml list
|
|
773
|
+
|
|
774
|
+
# 手动切换主库 (计划内维护)
|
|
775
|
+
patronictl -c /etc/patroni.yml switchover --master node1 --candidate node2
|
|
776
|
+
|
|
777
|
+
# 故障转移 (紧急)
|
|
778
|
+
patronictl -c /etc/patroni.yml failover
|
|
779
|
+
```
|
|
780
|
+
|
|
781
|
+
### 6.3 逻辑复制
|
|
782
|
+
|
|
783
|
+
```sql
|
|
784
|
+
-- 发布端 (源库)
|
|
785
|
+
CREATE PUBLICATION pub_orders FOR TABLE orders, order_items;
|
|
786
|
+
-- 或发布所有表
|
|
787
|
+
CREATE PUBLICATION pub_all FOR ALL TABLES;
|
|
788
|
+
|
|
789
|
+
-- 订阅端 (目标库)
|
|
790
|
+
CREATE SUBSCRIPTION sub_orders
|
|
791
|
+
CONNECTION 'host=source_host dbname=mydb user=replicator password=...'
|
|
792
|
+
PUBLICATION pub_orders;
|
|
793
|
+
|
|
794
|
+
-- 监控逻辑复制
|
|
795
|
+
SELECT * FROM pg_stat_subscription;
|
|
796
|
+
SELECT * FROM pg_replication_slots;
|
|
797
|
+
```
|
|
798
|
+
|
|
799
|
+
---
|
|
800
|
+
|
|
801
|
+
## 7. 备份与恢复
|
|
802
|
+
|
|
803
|
+
### 7.1 pg_dump / pg_restore
|
|
804
|
+
|
|
805
|
+
```bash
|
|
806
|
+
# 逻辑备份 - 自定义格式 (推荐,可并行恢复)
|
|
807
|
+
pg_dump -h localhost -U postgres -Fc -Z 6 -j 4 \
|
|
808
|
+
--no-owner --no-privileges \
|
|
809
|
+
-f /backup/mydb_$(date +%Y%m%d_%H%M%S).dump mydb
|
|
810
|
+
|
|
811
|
+
# 逻辑备份 - 纯 SQL (可读性好,不支持并行恢复)
|
|
812
|
+
pg_dump -h localhost -U postgres --schema-only -f schema.sql mydb
|
|
813
|
+
pg_dump -h localhost -U postgres --data-only -f data.sql mydb
|
|
814
|
+
|
|
815
|
+
# 恢复到新库
|
|
816
|
+
createdb -h localhost -U postgres mydb_restored
|
|
817
|
+
pg_restore -h localhost -U postgres -d mydb_restored -j 4 \
|
|
818
|
+
--no-owner --no-privileges \
|
|
819
|
+
/backup/mydb_20260328.dump
|
|
820
|
+
|
|
821
|
+
# 只恢复特定表
|
|
822
|
+
pg_restore -h localhost -U postgres -d mydb_restored \
|
|
823
|
+
-t orders -t order_items \
|
|
824
|
+
/backup/mydb_20260328.dump
|
|
825
|
+
```
|
|
826
|
+
|
|
827
|
+
### 7.2 pg_basebackup (物理备份)
|
|
828
|
+
|
|
829
|
+
```bash
|
|
830
|
+
# 全量物理备份
|
|
831
|
+
pg_basebackup -h primary_host -U replicator \
|
|
832
|
+
-D /backup/base_$(date +%Y%m%d) \
|
|
833
|
+
--wal-method=stream \
|
|
834
|
+
--checkpoint=fast \
|
|
835
|
+
--compress=gzip:6 \
|
|
836
|
+
--progress --verbose
|
|
837
|
+
|
|
838
|
+
# 备份到 tar 格式
|
|
839
|
+
pg_basebackup -h primary_host -U replicator \
|
|
840
|
+
-D /backup/ --format=tar --gzip \
|
|
841
|
+
--wal-method=stream
|
|
842
|
+
```
|
|
843
|
+
|
|
844
|
+
### 7.3 PITR (时间点恢复)
|
|
845
|
+
|
|
846
|
+
```bash
|
|
847
|
+
# 前提: 开启 WAL 归档
|
|
848
|
+
# postgresql.conf:
|
|
849
|
+
# archive_mode = on
|
|
850
|
+
# archive_command = 'cp %p /archive/%f'
|
|
851
|
+
# 或使用 pgbackrest / barman
|
|
852
|
+
|
|
853
|
+
# 恢复步骤:
|
|
854
|
+
# 1. 停止 PostgreSQL
|
|
855
|
+
# 2. 备份当前数据目录
|
|
856
|
+
# 3. 从 base backup 还原数据目录
|
|
857
|
+
# 4. 创建 recovery 配置
|
|
858
|
+
|
|
859
|
+
# postgresql.conf (PostgreSQL 12+):
|
|
860
|
+
# restore_command = 'cp /archive/%f %p'
|
|
861
|
+
# recovery_target_time = '2026-03-28 10:30:00+08'
|
|
862
|
+
# recovery_target_action = 'promote'
|
|
863
|
+
```
|
|
864
|
+
|
|
865
|
+
```sql
|
|
866
|
+
-- 创建还原点 (在重大变更前)
|
|
867
|
+
SELECT pg_create_restore_point('before_migration_v2');
|
|
868
|
+
|
|
869
|
+
-- 恢复到指定还原点
|
|
870
|
+
-- recovery_target_name = 'before_migration_v2'
|
|
871
|
+
-- recovery_target_action = 'promote'
|
|
872
|
+
```
|
|
873
|
+
|
|
874
|
+
---
|
|
875
|
+
|
|
876
|
+
## 8. 安全
|
|
877
|
+
|
|
878
|
+
### 8.1 角色与权限
|
|
879
|
+
|
|
880
|
+
```sql
|
|
881
|
+
-- 创建应用角色 (最小权限原则)
|
|
882
|
+
CREATE ROLE app_readonly WITH LOGIN PASSWORD 'readonly_pass';
|
|
883
|
+
CREATE ROLE app_readwrite WITH LOGIN PASSWORD 'readwrite_pass';
|
|
884
|
+
CREATE ROLE app_admin WITH LOGIN PASSWORD 'admin_pass';
|
|
885
|
+
|
|
886
|
+
-- 只读角色
|
|
887
|
+
GRANT CONNECT ON DATABASE mydb TO app_readonly;
|
|
888
|
+
GRANT USAGE ON SCHEMA public TO app_readonly;
|
|
889
|
+
GRANT SELECT ON ALL TABLES IN SCHEMA public TO app_readonly;
|
|
890
|
+
ALTER DEFAULT PRIVILEGES IN SCHEMA public
|
|
891
|
+
GRANT SELECT ON TABLES TO app_readonly;
|
|
892
|
+
|
|
893
|
+
-- 读写角色
|
|
894
|
+
GRANT CONNECT ON DATABASE mydb TO app_readwrite;
|
|
895
|
+
GRANT USAGE ON SCHEMA public TO app_readwrite;
|
|
896
|
+
GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO app_readwrite;
|
|
897
|
+
GRANT USAGE, SELECT ON ALL SEQUENCES IN SCHEMA public TO app_readwrite;
|
|
898
|
+
ALTER DEFAULT PRIVILEGES IN SCHEMA public
|
|
899
|
+
GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO app_readwrite;
|
|
900
|
+
ALTER DEFAULT PRIVILEGES IN SCHEMA public
|
|
901
|
+
GRANT USAGE, SELECT ON SEQUENCES TO app_readwrite;
|
|
902
|
+
|
|
903
|
+
-- 禁止直接用 superuser 连接应用
|
|
904
|
+
-- pg_hba.conf:
|
|
905
|
+
-- local all postgres peer
|
|
906
|
+
-- host all postgres 127.0.0.1/32 reject
|
|
907
|
+
```
|
|
908
|
+
|
|
909
|
+
### 8.2 行级安全 (RLS)
|
|
910
|
+
|
|
911
|
+
```sql
|
|
912
|
+
-- 启用 RLS
|
|
913
|
+
ALTER TABLE tenant_data ENABLE ROW LEVEL SECURITY;
|
|
914
|
+
|
|
915
|
+
-- 多租户隔离策略
|
|
916
|
+
CREATE POLICY tenant_isolation ON tenant_data
|
|
917
|
+
USING (tenant_id = current_setting('app.current_tenant')::INTEGER);
|
|
918
|
+
|
|
919
|
+
-- 应用层设置租户上下文
|
|
920
|
+
SET app.current_tenant = '42';
|
|
921
|
+
SELECT * FROM tenant_data; -- 只能看到 tenant_id=42 的数据
|
|
922
|
+
|
|
923
|
+
-- 管理员绕过策略
|
|
924
|
+
CREATE POLICY admin_all ON tenant_data
|
|
925
|
+
TO app_admin
|
|
926
|
+
USING (true);
|
|
927
|
+
|
|
928
|
+
-- 写入策略 (WITH CHECK 控制可插入/更新的行)
|
|
929
|
+
CREATE POLICY tenant_insert ON tenant_data
|
|
930
|
+
FOR INSERT
|
|
931
|
+
WITH CHECK (tenant_id = current_setting('app.current_tenant')::INTEGER);
|
|
932
|
+
|
|
933
|
+
-- 强制 RLS 对表属主也生效
|
|
934
|
+
ALTER TABLE tenant_data FORCE ROW LEVEL SECURITY;
|
|
935
|
+
```
|
|
936
|
+
|
|
937
|
+
### 8.3 SSL/TLS 连接
|
|
938
|
+
|
|
939
|
+
```bash
|
|
940
|
+
# postgresql.conf
|
|
941
|
+
# ssl = on
|
|
942
|
+
# ssl_cert_file = '/etc/ssl/certs/server.crt'
|
|
943
|
+
# ssl_key_file = '/etc/ssl/private/server.key'
|
|
944
|
+
# ssl_ca_file = '/etc/ssl/certs/ca.crt'
|
|
945
|
+
# ssl_min_protocol_version = 'TLSv1.3'
|
|
946
|
+
|
|
947
|
+
# pg_hba.conf - 强制 SSL
|
|
948
|
+
# hostssl all all 0.0.0.0/0 scram-sha-256
|
|
949
|
+
|
|
950
|
+
# 客户端连接
|
|
951
|
+
# psql "host=db.example.com dbname=mydb user=app sslmode=verify-full sslrootcert=ca.crt"
|
|
952
|
+
```
|
|
953
|
+
|
|
954
|
+
```sql
|
|
955
|
+
-- 验证 SSL 连接
|
|
956
|
+
SELECT ssl, version, cipher FROM pg_stat_ssl
|
|
957
|
+
WHERE pid = pg_backend_pid();
|
|
958
|
+
|
|
959
|
+
-- 查看所有连接的 SSL 状态
|
|
960
|
+
SELECT s.pid, s.usename, s.client_addr, l.ssl, l.version, l.cipher
|
|
961
|
+
FROM pg_stat_activity s
|
|
962
|
+
LEFT JOIN pg_stat_ssl l ON s.pid = l.pid
|
|
963
|
+
WHERE s.state = 'active';
|
|
964
|
+
```
|
|
965
|
+
|
|
966
|
+
### 8.4 审计日志
|
|
967
|
+
|
|
968
|
+
```sql
|
|
969
|
+
-- 使用 pgaudit 扩展
|
|
970
|
+
CREATE EXTENSION IF NOT EXISTS pgaudit;
|
|
971
|
+
|
|
972
|
+
-- postgresql.conf
|
|
973
|
+
-- pgaudit.log = 'write, ddl'
|
|
974
|
+
-- pgaudit.log_catalog = off
|
|
975
|
+
-- pgaudit.log_relation = on
|
|
976
|
+
|
|
977
|
+
-- 对特定角色开启审计
|
|
978
|
+
ALTER ROLE app_readwrite SET pgaudit.log = 'write';
|
|
979
|
+
```
|
|
980
|
+
|
|
981
|
+
---
|
|
982
|
+
|
|
983
|
+
## 9. 监控
|
|
984
|
+
|
|
985
|
+
### 9.1 pg_stat_statements
|
|
986
|
+
|
|
987
|
+
```sql
|
|
988
|
+
-- 启用扩展
|
|
989
|
+
CREATE EXTENSION IF NOT EXISTS pg_stat_statements;
|
|
990
|
+
|
|
991
|
+
-- postgresql.conf
|
|
992
|
+
-- shared_preload_libraries = 'pg_stat_statements'
|
|
993
|
+
-- pg_stat_statements.max = 10000
|
|
994
|
+
-- pg_stat_statements.track = all
|
|
995
|
+
|
|
996
|
+
-- Top 10 慢查询
|
|
997
|
+
SELECT
|
|
998
|
+
queryid,
|
|
999
|
+
calls,
|
|
1000
|
+
round(total_exec_time::numeric, 2) AS total_ms,
|
|
1001
|
+
round(mean_exec_time::numeric, 2) AS avg_ms,
|
|
1002
|
+
round(stddev_exec_time::numeric, 2) AS stddev_ms,
|
|
1003
|
+
rows,
|
|
1004
|
+
round((shared_blks_hit * 100.0 /
|
|
1005
|
+
NULLIF(shared_blks_hit + shared_blks_read, 0))::numeric, 2) AS cache_hit_pct,
|
|
1006
|
+
left(query, 120) AS query_preview
|
|
1007
|
+
FROM pg_stat_statements
|
|
1008
|
+
ORDER BY total_exec_time DESC
|
|
1009
|
+
LIMIT 10;
|
|
1010
|
+
|
|
1011
|
+
-- Top 10 IO 密集查询
|
|
1012
|
+
SELECT
|
|
1013
|
+
queryid,
|
|
1014
|
+
calls,
|
|
1015
|
+
shared_blks_read,
|
|
1016
|
+
shared_blks_written,
|
|
1017
|
+
temp_blks_read + temp_blks_written AS temp_blks_total,
|
|
1018
|
+
left(query, 120) AS query_preview
|
|
1019
|
+
FROM pg_stat_statements
|
|
1020
|
+
ORDER BY shared_blks_read + shared_blks_written DESC
|
|
1021
|
+
LIMIT 10;
|
|
1022
|
+
|
|
1023
|
+
-- 重置统计 (定期执行以保持时效性)
|
|
1024
|
+
SELECT pg_stat_statements_reset();
|
|
1025
|
+
```
|
|
1026
|
+
|
|
1027
|
+
### 9.2 pg_stat_activity
|
|
1028
|
+
|
|
1029
|
+
```sql
|
|
1030
|
+
-- 当前活跃连接
|
|
1031
|
+
SELECT
|
|
1032
|
+
pid,
|
|
1033
|
+
usename,
|
|
1034
|
+
client_addr,
|
|
1035
|
+
state,
|
|
1036
|
+
wait_event_type,
|
|
1037
|
+
wait_event,
|
|
1038
|
+
now() - query_start AS query_duration,
|
|
1039
|
+
left(query, 100) AS query_preview
|
|
1040
|
+
FROM pg_stat_activity
|
|
1041
|
+
WHERE state != 'idle'
|
|
1042
|
+
AND pid != pg_backend_pid()
|
|
1043
|
+
ORDER BY query_start;
|
|
1044
|
+
|
|
1045
|
+
-- 查找长事务(超过5分钟)
|
|
1046
|
+
SELECT
|
|
1047
|
+
pid,
|
|
1048
|
+
usename,
|
|
1049
|
+
now() - xact_start AS xact_duration,
|
|
1050
|
+
state,
|
|
1051
|
+
left(query, 150) AS query
|
|
1052
|
+
FROM pg_stat_activity
|
|
1053
|
+
WHERE xact_start IS NOT NULL
|
|
1054
|
+
AND now() - xact_start > INTERVAL '5 minutes'
|
|
1055
|
+
ORDER BY xact_start;
|
|
1056
|
+
|
|
1057
|
+
-- 终止问题查询
|
|
1058
|
+
SELECT pg_cancel_backend(pid); -- 温和取消 (仅取消当前查询)
|
|
1059
|
+
SELECT pg_terminate_backend(pid); -- 强制终止 (断开连接)
|
|
1060
|
+
|
|
1061
|
+
-- 批量终止空闲超时连接
|
|
1062
|
+
SELECT pg_terminate_backend(pid)
|
|
1063
|
+
FROM pg_stat_activity
|
|
1064
|
+
WHERE state = 'idle'
|
|
1065
|
+
AND now() - state_change > INTERVAL '30 minutes'
|
|
1066
|
+
AND usename != 'postgres';
|
|
1067
|
+
```
|
|
1068
|
+
|
|
1069
|
+
### 9.3 表和索引健康度
|
|
1070
|
+
|
|
1071
|
+
```sql
|
|
1072
|
+
-- 表级统计全景
|
|
1073
|
+
SELECT
|
|
1074
|
+
schemaname, relname,
|
|
1075
|
+
seq_scan, seq_tup_read,
|
|
1076
|
+
idx_scan, idx_tup_fetch,
|
|
1077
|
+
n_tup_ins, n_tup_upd, n_tup_del,
|
|
1078
|
+
n_live_tup, n_dead_tup,
|
|
1079
|
+
last_vacuum, last_autovacuum,
|
|
1080
|
+
last_analyze, last_autoanalyze
|
|
1081
|
+
FROM pg_stat_user_tables
|
|
1082
|
+
ORDER BY n_dead_tup DESC;
|
|
1083
|
+
|
|
1084
|
+
-- 缓存命中率 (应 > 99%)
|
|
1085
|
+
SELECT
|
|
1086
|
+
sum(heap_blks_read) AS heap_read,
|
|
1087
|
+
sum(heap_blks_hit) AS heap_hit,
|
|
1088
|
+
round(sum(heap_blks_hit) * 100.0 /
|
|
1089
|
+
NULLIF(sum(heap_blks_hit) + sum(heap_blks_read), 0), 2) AS cache_hit_pct
|
|
1090
|
+
FROM pg_statio_user_tables;
|
|
1091
|
+
|
|
1092
|
+
-- 索引缓存命中率
|
|
1093
|
+
SELECT
|
|
1094
|
+
sum(idx_blks_read) AS idx_read,
|
|
1095
|
+
sum(idx_blks_hit) AS idx_hit,
|
|
1096
|
+
round(sum(idx_blks_hit) * 100.0 /
|
|
1097
|
+
NULLIF(sum(idx_blks_hit) + sum(idx_blks_read), 0), 2) AS idx_cache_hit_pct
|
|
1098
|
+
FROM pg_statio_user_indexes;
|
|
1099
|
+
|
|
1100
|
+
-- 表和索引膨胀估算
|
|
1101
|
+
SELECT
|
|
1102
|
+
tablename,
|
|
1103
|
+
pg_size_pretty(pg_total_relation_size(schemaname || '.' || tablename)) AS total_size,
|
|
1104
|
+
pg_size_pretty(pg_relation_size(schemaname || '.' || tablename)) AS table_size,
|
|
1105
|
+
pg_size_pretty(pg_indexes_size(schemaname || '.' || tablename)) AS index_size
|
|
1106
|
+
FROM pg_tables
|
|
1107
|
+
WHERE schemaname = 'public'
|
|
1108
|
+
ORDER BY pg_total_relation_size(schemaname || '.' || tablename) DESC;
|
|
1109
|
+
```
|
|
1110
|
+
|
|
1111
|
+
---
|
|
1112
|
+
|
|
1113
|
+
## 10. 连接池 (PgBouncer)
|
|
1114
|
+
|
|
1115
|
+
### 10.1 配置
|
|
1116
|
+
|
|
1117
|
+
```ini
|
|
1118
|
+
; pgbouncer.ini
|
|
1119
|
+
[databases]
|
|
1120
|
+
mydb = host=127.0.0.1 port=5432 dbname=mydb
|
|
1121
|
+
|
|
1122
|
+
[pgbouncer]
|
|
1123
|
+
listen_addr = 0.0.0.0
|
|
1124
|
+
listen_port = 6432
|
|
1125
|
+
auth_type = scram-sha-256
|
|
1126
|
+
auth_file = /etc/pgbouncer/userlist.txt
|
|
1127
|
+
|
|
1128
|
+
; 连接池模式
|
|
1129
|
+
pool_mode = transaction ; 推荐: 事务级复用
|
|
1130
|
+
; pool_mode = session ; 会话级 (兼容性最好但效率最低)
|
|
1131
|
+
; pool_mode = statement ; 语句级 (不支持事务)
|
|
1132
|
+
|
|
1133
|
+
; 连接数控制
|
|
1134
|
+
default_pool_size = 25
|
|
1135
|
+
max_client_conn = 1000
|
|
1136
|
+
min_pool_size = 5
|
|
1137
|
+
reserve_pool_size = 5
|
|
1138
|
+
reserve_pool_timeout = 3
|
|
1139
|
+
|
|
1140
|
+
; 超时设置
|
|
1141
|
+
server_idle_timeout = 600
|
|
1142
|
+
client_idle_timeout = 0
|
|
1143
|
+
query_timeout = 300
|
|
1144
|
+
client_login_timeout = 60
|
|
1145
|
+
|
|
1146
|
+
; 日志
|
|
1147
|
+
log_connections = 1
|
|
1148
|
+
log_disconnections = 1
|
|
1149
|
+
log_pooler_errors = 1
|
|
1150
|
+
stats_period = 60
|
|
1151
|
+
```
|
|
1152
|
+
|
|
1153
|
+
### 10.2 监控
|
|
1154
|
+
|
|
1155
|
+
```sql
|
|
1156
|
+
-- 连接 PgBouncer 管理端口
|
|
1157
|
+
-- psql -h 127.0.0.1 -p 6432 -U pgbouncer pgbouncer
|
|
1158
|
+
|
|
1159
|
+
-- 查看连接池状态
|
|
1160
|
+
SHOW POOLS;
|
|
1161
|
+
|
|
1162
|
+
-- 查看客户端连接
|
|
1163
|
+
SHOW CLIENTS;
|
|
1164
|
+
|
|
1165
|
+
-- 查看后端服务器连接
|
|
1166
|
+
SHOW SERVERS;
|
|
1167
|
+
|
|
1168
|
+
-- 统计信息
|
|
1169
|
+
SHOW STATS;
|
|
1170
|
+
|
|
1171
|
+
-- 内存使用
|
|
1172
|
+
SHOW MEM;
|
|
1173
|
+
```
|
|
1174
|
+
|
|
1175
|
+
### 10.3 Transaction 模式注意事项
|
|
1176
|
+
|
|
1177
|
+
```sql
|
|
1178
|
+
-- 以下功能在 transaction 模式下不可用:
|
|
1179
|
+
-- 1. SET 命令 (会话级变量)
|
|
1180
|
+
-- 2. PREPARE / DEALLOCATE (预备语句)
|
|
1181
|
+
-- 3. LISTEN / NOTIFY
|
|
1182
|
+
-- 4. LOAD
|
|
1183
|
+
-- 5. 会话级 advisory lock
|
|
1184
|
+
|
|
1185
|
+
-- 解决 SET 问题: 使用函数内的局部设置
|
|
1186
|
+
-- 错误:
|
|
1187
|
+
SET work_mem = '256MB';
|
|
1188
|
+
SELECT ... complex query ...;
|
|
1189
|
+
|
|
1190
|
+
-- 正确:
|
|
1191
|
+
SET LOCAL work_mem = '256MB'; -- 仅在当前事务内生效
|
|
1192
|
+
SELECT ... complex query ...;
|
|
1193
|
+
COMMIT;
|
|
1194
|
+
|
|
1195
|
+
-- 或使用函数:
|
|
1196
|
+
CREATE FUNCTION heavy_query() RETURNS SETOF record AS $$
|
|
1197
|
+
BEGIN
|
|
1198
|
+
SET LOCAL work_mem = '256MB';
|
|
1199
|
+
RETURN QUERY SELECT ...;
|
|
1200
|
+
END;
|
|
1201
|
+
$$ LANGUAGE plpgsql;
|
|
1202
|
+
```
|
|
1203
|
+
|
|
1204
|
+
---
|
|
1205
|
+
|
|
1206
|
+
## 11. 性能调优
|
|
1207
|
+
|
|
1208
|
+
### 11.1 内存参数
|
|
1209
|
+
|
|
1210
|
+
```sql
|
|
1211
|
+
-- 查看当前设置
|
|
1212
|
+
SELECT name, setting, unit, context, short_desc
|
|
1213
|
+
FROM pg_settings
|
|
1214
|
+
WHERE name IN (
|
|
1215
|
+
'shared_buffers', 'effective_cache_size', 'work_mem',
|
|
1216
|
+
'maintenance_work_mem', 'wal_buffers', 'huge_pages'
|
|
1217
|
+
);
|
|
1218
|
+
|
|
1219
|
+
-- postgresql.conf 推荐设置:
|
|
1220
|
+
|
|
1221
|
+
-- shared_buffers: 总内存的 25% (上限不超过 8GB)
|
|
1222
|
+
-- 16GB 内存 -> shared_buffers = 4GB
|
|
1223
|
+
-- shared_buffers = '4GB'
|
|
1224
|
+
|
|
1225
|
+
-- effective_cache_size: 总内存的 75% (仅影响查询规划器的成本估算)
|
|
1226
|
+
-- effective_cache_size = '12GB'
|
|
1227
|
+
|
|
1228
|
+
-- work_mem: 每个排序/哈希操作的内存上限
|
|
1229
|
+
-- 注意: 每个连接的每个操作都独立分配
|
|
1230
|
+
-- 总消耗 ≈ work_mem × max_connections × 操作数
|
|
1231
|
+
-- work_mem = '64MB' -- 复杂分析查询
|
|
1232
|
+
-- work_mem = '16MB' -- OLTP 为主
|
|
1233
|
+
|
|
1234
|
+
-- maintenance_work_mem: VACUUM、CREATE INDEX 等维护操作
|
|
1235
|
+
-- maintenance_work_mem = '1GB'
|
|
1236
|
+
|
|
1237
|
+
-- wal_buffers: WAL 缓冲区,-1 表示自动 (shared_buffers 的 1/32)
|
|
1238
|
+
-- wal_buffers = '64MB'
|
|
1239
|
+
|
|
1240
|
+
-- huge_pages: 减少 TLB miss (Linux 需配置 vm.nr_hugepages)
|
|
1241
|
+
-- huge_pages = try
|
|
1242
|
+
```
|
|
1243
|
+
|
|
1244
|
+
### 11.2 WAL 和 Checkpoint 调优
|
|
1245
|
+
|
|
1246
|
+
```sql
|
|
1247
|
+
-- checkpoint_completion_target: 0.9 (将 checkpoint 写入分散在整个间隔内)
|
|
1248
|
+
-- checkpoint_timeout: 15min (两次 checkpoint 的最大间隔)
|
|
1249
|
+
-- max_wal_size: 4GB (触发 checkpoint 的 WAL 累积量上限)
|
|
1250
|
+
-- min_wal_size: 1GB
|
|
1251
|
+
|
|
1252
|
+
-- 监控 checkpoint 频率
|
|
1253
|
+
SELECT * FROM pg_stat_bgwriter;
|
|
1254
|
+
-- 关注: checkpoints_timed (正常) vs checkpoints_req (被迫)
|
|
1255
|
+
-- 被迫 checkpoint 过多说明 max_wal_size 太小
|
|
1256
|
+
|
|
1257
|
+
-- WAL 写入优化
|
|
1258
|
+
-- wal_compression = on -- 压缩全页写入 (减少 WAL 体积)
|
|
1259
|
+
-- full_page_writes = on -- 必须开启 (数据安全)
|
|
1260
|
+
```
|
|
1261
|
+
|
|
1262
|
+
### 11.3 查询规划器调优
|
|
1263
|
+
|
|
1264
|
+
```sql
|
|
1265
|
+
-- 并行查询
|
|
1266
|
+
-- max_parallel_workers_per_gather = 4
|
|
1267
|
+
-- max_parallel_workers = 8
|
|
1268
|
+
-- parallel_tuple_cost = 0.01
|
|
1269
|
+
-- parallel_setup_cost = 100
|
|
1270
|
+
|
|
1271
|
+
-- 验证并行执行
|
|
1272
|
+
EXPLAIN ANALYZE
|
|
1273
|
+
SELECT count(*) FROM orders WHERE total > 100;
|
|
1274
|
+
-- 应看到 Parallel Seq Scan 或 Parallel Index Scan
|
|
1275
|
+
|
|
1276
|
+
-- JIT 编译 (PostgreSQL 11+)
|
|
1277
|
+
-- jit = on
|
|
1278
|
+
-- jit_above_cost = 100000
|
|
1279
|
+
-- jit_inline_above_cost = 500000
|
|
1280
|
+
-- jit_optimize_above_cost = 500000
|
|
1281
|
+
|
|
1282
|
+
-- 对于 OLTP,可考虑关闭 JIT 以降低延迟
|
|
1283
|
+
-- SET jit = off;
|
|
1284
|
+
|
|
1285
|
+
-- random_page_cost: SSD 调低到 1.1 (默认 4.0 是 HDD 值)
|
|
1286
|
+
-- random_page_cost = 1.1
|
|
1287
|
+
-- seq_page_cost = 1.0
|
|
1288
|
+
-- effective_io_concurrency = 200 -- SSD 推荐
|
|
1289
|
+
|
|
1290
|
+
-- 统计目标 (对高基数列提高采样精度)
|
|
1291
|
+
ALTER TABLE orders ALTER COLUMN customer_id SET STATISTICS 1000; -- 默认100
|
|
1292
|
+
ANALYZE orders;
|
|
1293
|
+
```
|
|
1294
|
+
|
|
1295
|
+
---
|
|
1296
|
+
|
|
1297
|
+
## 12. 常见陷阱
|
|
1298
|
+
|
|
1299
|
+
### 12.1 N+1 查询
|
|
1300
|
+
|
|
1301
|
+
```sql
|
|
1302
|
+
-- 陷阱: 应用层循环查询
|
|
1303
|
+
-- Python 伪代码:
|
|
1304
|
+
-- orders = db.query("SELECT * FROM orders WHERE status = 'pending'")
|
|
1305
|
+
-- for order in orders:
|
|
1306
|
+
-- items = db.query(f"SELECT * FROM order_items WHERE order_id = {order.id}")
|
|
1307
|
+
-- # 100 个订单 = 101 次查询!
|
|
1308
|
+
|
|
1309
|
+
-- 解决: JOIN 或子查询一次获取
|
|
1310
|
+
SELECT o.*, json_agg(
|
|
1311
|
+
json_build_object('product_id', oi.product_id, 'quantity', oi.quantity, 'price', oi.unit_price)
|
|
1312
|
+
) AS items
|
|
1313
|
+
FROM orders o
|
|
1314
|
+
LEFT JOIN order_items oi ON oi.order_id = o.id
|
|
1315
|
+
WHERE o.status = 'pending'
|
|
1316
|
+
GROUP BY o.id;
|
|
1317
|
+
|
|
1318
|
+
-- 或使用 LATERAL JOIN (更灵活)
|
|
1319
|
+
SELECT o.*, items.data
|
|
1320
|
+
FROM orders o
|
|
1321
|
+
CROSS JOIN LATERAL (
|
|
1322
|
+
SELECT json_agg(oi.*) AS data
|
|
1323
|
+
FROM order_items oi
|
|
1324
|
+
WHERE oi.order_id = o.id
|
|
1325
|
+
) items
|
|
1326
|
+
WHERE o.status = 'pending';
|
|
1327
|
+
```
|
|
1328
|
+
|
|
1329
|
+
### 12.2 锁竞争
|
|
1330
|
+
|
|
1331
|
+
```sql
|
|
1332
|
+
-- 陷阱: DDL 操作阻塞所有查询
|
|
1333
|
+
ALTER TABLE orders ADD COLUMN notes TEXT;
|
|
1334
|
+
-- 获取 ACCESS EXCLUSIVE 锁,阻塞所有并发操作
|
|
1335
|
+
|
|
1336
|
+
-- 解决: 使用低锁级别操作
|
|
1337
|
+
-- 添加无默认值的可空列 (瞬时,不重写表)
|
|
1338
|
+
ALTER TABLE orders ADD COLUMN notes TEXT; -- OK,快速
|
|
1339
|
+
|
|
1340
|
+
-- 陷阱: 添加有默认值的列 (PostgreSQL 11 之前会重写表)
|
|
1341
|
+
-- PostgreSQL 11+ 不重写表,但旧版本注意
|
|
1342
|
+
|
|
1343
|
+
-- 陷阱: CREATE INDEX 锁表
|
|
1344
|
+
CREATE INDEX idx_orders_notes ON orders(notes); -- 锁表!
|
|
1345
|
+
|
|
1346
|
+
-- 解决: CONCURRENTLY (不锁表,但更慢)
|
|
1347
|
+
CREATE INDEX CONCURRENTLY idx_orders_notes ON orders(notes);
|
|
1348
|
+
|
|
1349
|
+
-- 陷阱: 长事务持有锁
|
|
1350
|
+
BEGIN;
|
|
1351
|
+
SELECT * FROM orders WHERE id = 1 FOR UPDATE;
|
|
1352
|
+
-- ... 应用层做了很久的处理 ...
|
|
1353
|
+
-- 其他事务等待 id=1 的行锁
|
|
1354
|
+
COMMIT;
|
|
1355
|
+
|
|
1356
|
+
-- 解决: 设置语句/锁超时
|
|
1357
|
+
SET statement_timeout = '30s';
|
|
1358
|
+
SET lock_timeout = '5s';
|
|
1359
|
+
SET idle_in_transaction_session_timeout = '60s';
|
|
1360
|
+
```
|
|
1361
|
+
|
|
1362
|
+
### 12.3 膨胀表 (Table Bloat)
|
|
1363
|
+
|
|
1364
|
+
```sql
|
|
1365
|
+
-- 陷阱: 大量 UPDATE/DELETE 后表膨胀,查询变慢
|
|
1366
|
+
-- 原因: 死元组占据空间,顺序扫描变慢
|
|
1367
|
+
|
|
1368
|
+
-- 诊断: 膨胀比估算
|
|
1369
|
+
SELECT
|
|
1370
|
+
schemaname, tablename,
|
|
1371
|
+
pg_size_pretty(pg_total_relation_size(schemaname || '.' || tablename)) AS total_size,
|
|
1372
|
+
n_live_tup,
|
|
1373
|
+
n_dead_tup,
|
|
1374
|
+
CASE WHEN n_live_tup > 0
|
|
1375
|
+
THEN round(n_dead_tup::numeric / n_live_tup * 100, 2)
|
|
1376
|
+
ELSE 0
|
|
1377
|
+
END AS bloat_ratio_pct,
|
|
1378
|
+
last_autovacuum
|
|
1379
|
+
FROM pg_stat_user_tables
|
|
1380
|
+
WHERE n_dead_tup > 10000
|
|
1381
|
+
ORDER BY n_dead_tup DESC;
|
|
1382
|
+
|
|
1383
|
+
-- 使用 pgstattuple 扩展精确测量
|
|
1384
|
+
CREATE EXTENSION IF NOT EXISTS pgstattuple;
|
|
1385
|
+
SELECT * FROM pgstattuple('orders');
|
|
1386
|
+
-- 关注: dead_tuple_percent, free_percent
|
|
1387
|
+
|
|
1388
|
+
-- 解决方案 1: 调优 autovacuum (推荐)
|
|
1389
|
+
ALTER TABLE orders SET (
|
|
1390
|
+
autovacuum_vacuum_scale_factor = 0.02,
|
|
1391
|
+
autovacuum_vacuum_cost_delay = 2, -- 加速 vacuum
|
|
1392
|
+
autovacuum_vacuum_cost_limit = 1000
|
|
1393
|
+
);
|
|
1394
|
+
|
|
1395
|
+
-- 解决方案 2: 在线重建 (pg_repack,不锁表)
|
|
1396
|
+
-- pg_repack --table orders --jobs 4 -d mydb
|
|
1397
|
+
|
|
1398
|
+
-- 解决方案 3: VACUUM FULL (锁表,紧急用)
|
|
1399
|
+
VACUUM FULL VERBOSE orders;
|
|
1400
|
+
```
|
|
1401
|
+
|
|
1402
|
+
### 12.4 连接泄漏
|
|
1403
|
+
|
|
1404
|
+
```sql
|
|
1405
|
+
-- 陷阱: 应用崩溃/异常后连接未释放
|
|
1406
|
+
-- 诊断
|
|
1407
|
+
SELECT count(*), state, usename
|
|
1408
|
+
FROM pg_stat_activity
|
|
1409
|
+
GROUP BY state, usename
|
|
1410
|
+
ORDER BY count DESC;
|
|
1411
|
+
|
|
1412
|
+
-- 大量 idle 连接消耗内存
|
|
1413
|
+
-- 每个连接约占 5-10MB 内存
|
|
1414
|
+
|
|
1415
|
+
-- 解决: 设置 idle 超时
|
|
1416
|
+
-- idle_in_transaction_session_timeout = '60s' -- 空闲事务超时
|
|
1417
|
+
-- idle_session_timeout = '3600s' -- PostgreSQL 14+ 空闲会话超时
|
|
1418
|
+
|
|
1419
|
+
-- 解决: 使用 PgBouncer 限制实际连接数 (见第10章)
|
|
1420
|
+
```
|
|
1421
|
+
|
|
1422
|
+
### 12.5 不安全的类型转换
|
|
1423
|
+
|
|
1424
|
+
```sql
|
|
1425
|
+
-- 陷阱: 隐式转换导致索引失效
|
|
1426
|
+
-- 假设 phone 列是 VARCHAR
|
|
1427
|
+
SELECT * FROM customers WHERE phone = 13800138000;
|
|
1428
|
+
-- PostgreSQL 把 VARCHAR 转为 NUMERIC 比较,索引失效!
|
|
1429
|
+
|
|
1430
|
+
-- 解决: 保持类型一致
|
|
1431
|
+
SELECT * FROM customers WHERE phone = '13800138000';
|
|
1432
|
+
|
|
1433
|
+
-- 陷阱: JSONB 数值比较
|
|
1434
|
+
SELECT * FROM products WHERE (attributes ->> 'price')::numeric > 100;
|
|
1435
|
+
-- 每次都做类型转换,无法用索引
|
|
1436
|
+
|
|
1437
|
+
-- 解决: 表达式索引
|
|
1438
|
+
CREATE INDEX idx_products_price ON products(((attributes ->> 'price')::numeric));
|
|
1439
|
+
```
|
|
1440
|
+
|
|
1441
|
+
### 12.6 错误的分页实现
|
|
1442
|
+
|
|
1443
|
+
```sql
|
|
1444
|
+
-- 陷阱: OFFSET 越大越慢
|
|
1445
|
+
SELECT * FROM orders ORDER BY id LIMIT 20 OFFSET 100000;
|
|
1446
|
+
-- 数据库必须扫描前 100020 行然后丢弃 100000 行
|
|
1447
|
+
|
|
1448
|
+
-- 解决: 游标分页 (Keyset Pagination)
|
|
1449
|
+
-- 第一页
|
|
1450
|
+
SELECT * FROM orders ORDER BY id LIMIT 20;
|
|
1451
|
+
|
|
1452
|
+
-- 后续页 (假设上一页最后一条 id=100020)
|
|
1453
|
+
SELECT * FROM orders WHERE id > 100020 ORDER BY id LIMIT 20;
|
|
1454
|
+
-- 利用索引直接定位,性能恒定
|
|
1455
|
+
|
|
1456
|
+
-- 复合排序的游标分页
|
|
1457
|
+
SELECT * FROM orders
|
|
1458
|
+
WHERE (ordered_at, id) < ('2026-03-27 10:00:00', 99999)
|
|
1459
|
+
ORDER BY ordered_at DESC, id DESC
|
|
1460
|
+
LIMIT 20;
|
|
1461
|
+
```
|
|
1462
|
+
|
|
1463
|
+
---
|
|
1464
|
+
|
|
1465
|
+
## 13. 实用运维 SQL
|
|
1466
|
+
|
|
1467
|
+
### 13.1 表空间管理
|
|
1468
|
+
|
|
1469
|
+
```sql
|
|
1470
|
+
-- 数据库大小
|
|
1471
|
+
SELECT pg_size_pretty(pg_database_size(current_database())) AS db_size;
|
|
1472
|
+
|
|
1473
|
+
-- 各表大小排名
|
|
1474
|
+
SELECT
|
|
1475
|
+
relname AS table_name,
|
|
1476
|
+
pg_size_pretty(pg_total_relation_size(oid)) AS total,
|
|
1477
|
+
pg_size_pretty(pg_relation_size(oid)) AS data,
|
|
1478
|
+
pg_size_pretty(pg_indexes_size(oid)) AS indexes,
|
|
1479
|
+
pg_size_pretty(pg_total_relation_size(oid) - pg_relation_size(oid) - pg_indexes_size(oid)) AS toast
|
|
1480
|
+
FROM pg_class
|
|
1481
|
+
WHERE relkind = 'r' AND relnamespace = 'public'::regnamespace
|
|
1482
|
+
ORDER BY pg_total_relation_size(oid) DESC
|
|
1483
|
+
LIMIT 20;
|
|
1484
|
+
```
|
|
1485
|
+
|
|
1486
|
+
### 13.2 序列管理
|
|
1487
|
+
|
|
1488
|
+
```sql
|
|
1489
|
+
-- 查看所有序列当前值
|
|
1490
|
+
SELECT
|
|
1491
|
+
sequencename,
|
|
1492
|
+
last_value,
|
|
1493
|
+
start_value,
|
|
1494
|
+
max_value,
|
|
1495
|
+
increment_by
|
|
1496
|
+
FROM pg_sequences
|
|
1497
|
+
WHERE schemaname = 'public';
|
|
1498
|
+
|
|
1499
|
+
-- 重置序列到最大已用值(数据导入后)
|
|
1500
|
+
SELECT setval('orders_id_seq', (SELECT max(id) FROM orders));
|
|
1501
|
+
```
|
|
1502
|
+
|
|
1503
|
+
### 13.3 批量数据操作
|
|
1504
|
+
|
|
1505
|
+
```sql
|
|
1506
|
+
-- 高效批量插入
|
|
1507
|
+
-- 方法1: COPY (最快)
|
|
1508
|
+
COPY orders(customer_id, status, total, ordered_at)
|
|
1509
|
+
FROM '/tmp/orders.csv' WITH (FORMAT csv, HEADER true);
|
|
1510
|
+
|
|
1511
|
+
-- 方法2: 多值 INSERT
|
|
1512
|
+
INSERT INTO orders(customer_id, status, total)
|
|
1513
|
+
VALUES
|
|
1514
|
+
(1, 'pending', 99.99),
|
|
1515
|
+
(2, 'pending', 149.50),
|
|
1516
|
+
(3, 'confirmed', 200.00);
|
|
1517
|
+
|
|
1518
|
+
-- 方法3: INSERT ... SELECT
|
|
1519
|
+
INSERT INTO orders_archive
|
|
1520
|
+
SELECT * FROM orders WHERE ordered_at < '2025-01-01';
|
|
1521
|
+
|
|
1522
|
+
-- 高效批量更新 (避免逐行 UPDATE)
|
|
1523
|
+
UPDATE products p
|
|
1524
|
+
SET price = t.new_price
|
|
1525
|
+
FROM (VALUES
|
|
1526
|
+
(1, 19.99),
|
|
1527
|
+
(2, 29.99),
|
|
1528
|
+
(3, 39.99)
|
|
1529
|
+
) AS t(id, new_price)
|
|
1530
|
+
WHERE p.id = t.id;
|
|
1531
|
+
|
|
1532
|
+
-- 高效批量删除 (大表分批删除,避免长事务)
|
|
1533
|
+
DO $$
|
|
1534
|
+
DECLARE
|
|
1535
|
+
batch_size INTEGER := 10000;
|
|
1536
|
+
deleted INTEGER;
|
|
1537
|
+
BEGIN
|
|
1538
|
+
LOOP
|
|
1539
|
+
DELETE FROM event_logs
|
|
1540
|
+
WHERE id IN (
|
|
1541
|
+
SELECT id FROM event_logs
|
|
1542
|
+
WHERE event_time < '2025-01-01'
|
|
1543
|
+
LIMIT batch_size
|
|
1544
|
+
);
|
|
1545
|
+
GET DIAGNOSTICS deleted = ROW_COUNT;
|
|
1546
|
+
RAISE NOTICE 'Deleted % rows', deleted;
|
|
1547
|
+
EXIT WHEN deleted < batch_size;
|
|
1548
|
+
PERFORM pg_sleep(0.1); -- 释放锁压力
|
|
1549
|
+
COMMIT;
|
|
1550
|
+
END LOOP;
|
|
1551
|
+
END $$;
|
|
1552
|
+
```
|
|
1553
|
+
|
|
1554
|
+
---
|
|
1555
|
+
|
|
1556
|
+
## Agent Checklist
|
|
1557
|
+
|
|
1558
|
+
以下检查项用于 UmaDev 流水线的数据层质量门禁。
|
|
1559
|
+
|
|
1560
|
+
### 设计阶段
|
|
1561
|
+
|
|
1562
|
+
- [ ] 表设计遵循命名规范:小写 snake_case,表名复数
|
|
1563
|
+
- [ ] 主键使用 `BIGINT GENERATED ALWAYS AS IDENTITY`(非 SERIAL)
|
|
1564
|
+
- [ ] 外键约束明确 `ON DELETE` / `ON UPDATE` 行为
|
|
1565
|
+
- [ ] 金额字段使用 `NUMERIC(p,s)` 而非浮点型
|
|
1566
|
+
- [ ] 时间字段使用 `TIMESTAMPTZ`(非 TIMESTAMP)
|
|
1567
|
+
- [ ] JSONB 字段有明确的结构文档和 GIN 索引
|
|
1568
|
+
- [ ] CHECK 约束覆盖业务不变量
|
|
1569
|
+
- [ ] 分区策略已评估(单表预期超过 1000 万行时)
|
|
1570
|
+
|
|
1571
|
+
### 索引阶段
|
|
1572
|
+
|
|
1573
|
+
- [ ] 所有外键列已建索引
|
|
1574
|
+
- [ ] 高频查询的 WHERE/JOIN/ORDER BY 列有对应索引
|
|
1575
|
+
- [ ] 部分索引用于过滤活跃子集
|
|
1576
|
+
- [ ] 覆盖索引用于高频只读查询
|
|
1577
|
+
- [ ] 全文搜索使用 GIN + tsvector 而非 LIKE '%keyword%'
|
|
1578
|
+
- [ ] 未使用的索引已清理(pg_stat_user_indexes.idx_scan = 0)
|
|
1579
|
+
|
|
1580
|
+
### 查询阶段
|
|
1581
|
+
|
|
1582
|
+
- [ ] 核心查询已通过 EXPLAIN ANALYZE 验证
|
|
1583
|
+
- [ ] 无 Seq Scan on 大表(除非有意为之)
|
|
1584
|
+
- [ ] 分页使用游标分页而非 OFFSET
|
|
1585
|
+
- [ ] N+1 查询已用 JOIN/子查询/LATERAL 消除
|
|
1586
|
+
- [ ] CTE 未导致优化屏障(检查 NOT MATERIALIZED)
|
|
1587
|
+
- [ ] 统计信息更新频率已调优
|
|
1588
|
+
|
|
1589
|
+
### 安全阶段
|
|
1590
|
+
|
|
1591
|
+
- [ ] 应用使用最小权限角色连接(非 superuser)
|
|
1592
|
+
- [ ] 多租户场景启用 RLS
|
|
1593
|
+
- [ ] SSL/TLS 强制开启
|
|
1594
|
+
- [ ] pg_hba.conf 仅允许必要 IP 段
|
|
1595
|
+
- [ ] 密码使用 scram-sha-256 认证
|
|
1596
|
+
- [ ] pgaudit 审计已配置
|
|
1597
|
+
|
|
1598
|
+
### 运维阶段
|
|
1599
|
+
|
|
1600
|
+
- [ ] pg_stat_statements 已启用
|
|
1601
|
+
- [ ] autovacuum 参数已调优(非默认值)
|
|
1602
|
+
- [ ] 连接池 (PgBouncer) 已部署
|
|
1603
|
+
- [ ] shared_buffers / work_mem / effective_cache_size 已按内存调优
|
|
1604
|
+
- [ ] WAL 级别设为 replica 或 logical
|
|
1605
|
+
- [ ] 自动备份已配置(pg_basebackup + WAL 归档)
|
|
1606
|
+
- [ ] PITR 恢复已验证
|
|
1607
|
+
- [ ] 监控告警已覆盖:复制延迟、连接数、缓存命中率、死元组比例
|
|
1608
|
+
- [ ] 长事务 / 空闲事务超时已设置
|
|
1609
|
+
- [ ] 定期检查未使用索引和膨胀表
|
|
1610
|
+
|
|
1611
|
+
---
|
|
1612
|
+
|
|
1613
|
+
> 文档版本: v1.0 | 最后更新: 2026-03-28 | 维护者: UmaDev Knowledge Base
|