@mytechtoday/augment-extensions 0.1.2 → 0.4.0
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/README.md +614 -39
- package/augment-extensions/coding-standards/bash/README.md +196 -0
- package/augment-extensions/coding-standards/bash/module.json +163 -0
- package/augment-extensions/coding-standards/bash/rules/naming-conventions.md +336 -0
- package/augment-extensions/coding-standards/bash/rules/universal-standards.md +289 -0
- package/augment-extensions/coding-standards/css/README.md +40 -0
- package/augment-extensions/coding-standards/css/examples/css-examples.css +550 -0
- package/augment-extensions/coding-standards/css/module.json +44 -0
- package/augment-extensions/coding-standards/css/rules/css-modern-features.md +448 -0
- package/augment-extensions/coding-standards/css/rules/css-standards.md +492 -0
- package/augment-extensions/coding-standards/html/README.md +40 -0
- package/augment-extensions/coding-standards/html/examples/html-examples.html +267 -0
- package/augment-extensions/coding-standards/html/examples/responsive-layout.html +505 -0
- package/augment-extensions/coding-standards/html/module.json +44 -0
- package/augment-extensions/coding-standards/html/rules/html-standards.md +349 -0
- package/augment-extensions/coding-standards/html-css-js/README.md +194 -0
- package/augment-extensions/coding-standards/html-css-js/examples/async-examples.js +487 -0
- package/augment-extensions/coding-standards/html-css-js/examples/css-examples.css +550 -0
- package/augment-extensions/coding-standards/html-css-js/examples/dom-examples.js +667 -0
- package/augment-extensions/coding-standards/html-css-js/examples/html-examples.html +267 -0
- package/augment-extensions/coding-standards/html-css-js/examples/javascript-examples.js +612 -0
- package/augment-extensions/coding-standards/html-css-js/examples/responsive-layout.html +505 -0
- package/augment-extensions/coding-standards/html-css-js/module.json +48 -0
- package/augment-extensions/coding-standards/html-css-js/rules/async-patterns.md +515 -0
- package/augment-extensions/coding-standards/html-css-js/rules/css-modern-features.md +448 -0
- package/augment-extensions/coding-standards/html-css-js/rules/css-standards.md +492 -0
- package/augment-extensions/coding-standards/html-css-js/rules/dom-manipulation.md +439 -0
- package/augment-extensions/coding-standards/html-css-js/rules/html-standards.md +349 -0
- package/augment-extensions/coding-standards/html-css-js/rules/javascript-standards.md +486 -0
- package/augment-extensions/coding-standards/html-css-js/rules/performance.md +463 -0
- package/augment-extensions/coding-standards/html-css-js/rules/tooling.md +543 -0
- package/augment-extensions/coding-standards/js/README.md +46 -0
- package/augment-extensions/coding-standards/js/examples/async-examples.js +487 -0
- package/augment-extensions/coding-standards/js/examples/dom-examples.js +667 -0
- package/augment-extensions/coding-standards/js/examples/javascript-examples.js +612 -0
- package/augment-extensions/coding-standards/js/module.json +49 -0
- package/augment-extensions/coding-standards/js/rules/async-patterns.md +515 -0
- package/augment-extensions/coding-standards/js/rules/dom-manipulation.md +439 -0
- package/augment-extensions/coding-standards/js/rules/javascript-standards.md +486 -0
- package/augment-extensions/coding-standards/js/rules/performance.md +463 -0
- package/augment-extensions/coding-standards/js/rules/tooling.md +543 -0
- package/augment-extensions/coding-standards/php/README.md +248 -0
- package/augment-extensions/coding-standards/php/examples/api-endpoint-example.php +204 -0
- package/augment-extensions/coding-standards/php/examples/cli-command-example.php +206 -0
- package/augment-extensions/coding-standards/php/examples/legacy-refactoring-example.php +234 -0
- package/augment-extensions/coding-standards/php/examples/web-application-example.php +211 -0
- package/augment-extensions/coding-standards/php/examples/woocommerce-extension-example.php +215 -0
- package/augment-extensions/coding-standards/php/examples/wordpress-plugin-example.php +189 -0
- package/augment-extensions/coding-standards/php/module.json +166 -0
- package/augment-extensions/coding-standards/php/rules/api-development.md +480 -0
- package/augment-extensions/coding-standards/php/rules/category-configuration.md +332 -0
- package/augment-extensions/coding-standards/php/rules/cli-tools.md +472 -0
- package/augment-extensions/coding-standards/php/rules/cms-integration.md +561 -0
- package/augment-extensions/coding-standards/php/rules/code-quality.md +402 -0
- package/augment-extensions/coding-standards/php/rules/documentation.md +425 -0
- package/augment-extensions/coding-standards/php/rules/ecommerce.md +627 -0
- package/augment-extensions/coding-standards/php/rules/error-handling.md +336 -0
- package/augment-extensions/coding-standards/php/rules/legacy-migration.md +677 -0
- package/augment-extensions/coding-standards/php/rules/naming-conventions.md +279 -0
- package/augment-extensions/coding-standards/php/rules/performance.md +392 -0
- package/augment-extensions/coding-standards/php/rules/psr-standards.md +186 -0
- package/augment-extensions/coding-standards/php/rules/security.md +358 -0
- package/augment-extensions/coding-standards/php/rules/testing.md +403 -0
- package/augment-extensions/coding-standards/php/rules/type-declarations.md +331 -0
- package/augment-extensions/coding-standards/php/rules/web-applications.md +426 -0
- package/augment-extensions/coding-standards/powershell/README.md +154 -0
- package/augment-extensions/coding-standards/powershell/examples/admin-example.ps1 +272 -0
- package/augment-extensions/coding-standards/powershell/examples/automation-example.ps1 +173 -0
- package/augment-extensions/coding-standards/powershell/examples/cloud-example.ps1 +243 -0
- package/augment-extensions/coding-standards/powershell/examples/cross-platform-example.ps1 +297 -0
- package/augment-extensions/coding-standards/powershell/examples/dsc-example.ps1 +224 -0
- package/augment-extensions/coding-standards/powershell/examples/legacy-migration-example.ps1 +340 -0
- package/augment-extensions/coding-standards/powershell/examples/module-example.psm1 +255 -0
- package/augment-extensions/coding-standards/powershell/module.json +165 -0
- package/augment-extensions/coding-standards/powershell/rules/administrative-tools.md +439 -0
- package/augment-extensions/coding-standards/powershell/rules/automation-scripts.md +240 -0
- package/augment-extensions/coding-standards/powershell/rules/cloud-orchestration.md +384 -0
- package/augment-extensions/coding-standards/powershell/rules/configuration-schema.md +383 -0
- package/augment-extensions/coding-standards/powershell/rules/cross-platform-scripts.md +482 -0
- package/augment-extensions/coding-standards/powershell/rules/dsc-configurations.md +296 -0
- package/augment-extensions/coding-standards/powershell/rules/error-handling.md +314 -0
- package/augment-extensions/coding-standards/powershell/rules/legacy-migrations.md +466 -0
- package/augment-extensions/coding-standards/powershell/rules/modules-functions.md +244 -0
- package/augment-extensions/coding-standards/powershell/rules/naming-conventions.md +266 -0
- package/augment-extensions/coding-standards/powershell/rules/performance-optimization.md +209 -0
- package/augment-extensions/coding-standards/powershell/rules/security-practices.md +314 -0
- package/augment-extensions/coding-standards/powershell/rules/testing-guidelines.md +268 -0
- package/augment-extensions/coding-standards/powershell/rules/universal-standards.md +197 -0
- package/augment-extensions/coding-standards/python/README.md +12 -8
- package/augment-extensions/coding-standards/python/examples/best-practices.py +373 -0
- package/augment-extensions/coding-standards/python/module.json +8 -4
- package/augment-extensions/coding-standards/python/rules/async-patterns.md +884 -0
- package/augment-extensions/coding-standards/python/rules/documentation.md +831 -0
- package/augment-extensions/coding-standards/python/rules/error-handling.md +855 -68
- package/augment-extensions/coding-standards/python/rules/testing.md +409 -0
- package/augment-extensions/coding-standards/python/rules/tooling.md +446 -0
- package/augment-extensions/coding-standards/python/rules/type-hints.md +115 -50
- package/augment-extensions/collections/html-css-js/README.md +82 -0
- package/augment-extensions/collections/html-css-js/collection.json +41 -0
- package/augment-extensions/domain-rules/database/README.md +161 -0
- package/augment-extensions/domain-rules/database/examples/flat-database-example.md +793 -0
- package/augment-extensions/domain-rules/database/examples/hybrid-database-example.md +1132 -0
- package/augment-extensions/domain-rules/database/examples/nosql-document-example.md +868 -0
- package/augment-extensions/domain-rules/database/examples/nosql-graph-example.md +805 -0
- package/augment-extensions/domain-rules/database/examples/relational-schema-example.md +621 -0
- package/augment-extensions/domain-rules/database/examples/vector-database-example.md +965 -0
- package/augment-extensions/domain-rules/database/module.json +28 -0
- package/augment-extensions/domain-rules/database/rules/flat-databases.md +624 -0
- package/augment-extensions/domain-rules/database/rules/nosql-databases.md +588 -0
- package/augment-extensions/domain-rules/database/rules/nosql-document-stores.md +856 -0
- package/augment-extensions/domain-rules/database/rules/nosql-graph-databases.md +778 -0
- package/augment-extensions/domain-rules/database/rules/nosql-key-value-stores.md +963 -0
- package/augment-extensions/domain-rules/database/rules/performance-optimization.md +1076 -0
- package/augment-extensions/domain-rules/database/rules/relational-databases.md +697 -0
- package/augment-extensions/domain-rules/database/rules/relational-indexing.md +671 -0
- package/augment-extensions/domain-rules/database/rules/relational-query-optimization.md +607 -0
- package/augment-extensions/domain-rules/database/rules/relational-schema-design.md +907 -0
- package/augment-extensions/domain-rules/database/rules/relational-transactions.md +783 -0
- package/augment-extensions/domain-rules/database/rules/security-standards.md +980 -0
- package/augment-extensions/domain-rules/database/rules/universal-best-practices.md +485 -0
- package/augment-extensions/domain-rules/database/rules/vector-databases.md +521 -0
- package/augment-extensions/domain-rules/database/rules/vector-embeddings.md +858 -0
- package/augment-extensions/domain-rules/database/rules/vector-indexing.md +934 -0
- package/augment-extensions/domain-rules/mcp/README.md +150 -0
- package/augment-extensions/domain-rules/mcp/examples/compressed-example.md +522 -0
- package/augment-extensions/domain-rules/mcp/examples/graph-augmented-example.md +520 -0
- package/augment-extensions/domain-rules/mcp/examples/hybrid-example.md +570 -0
- package/augment-extensions/domain-rules/mcp/examples/state-based-example.md +427 -0
- package/augment-extensions/domain-rules/mcp/examples/token-based-example.md +435 -0
- package/augment-extensions/domain-rules/mcp/examples/vector-based-example.md +502 -0
- package/augment-extensions/domain-rules/mcp/module.json +49 -0
- package/augment-extensions/domain-rules/mcp/rules/compressed-mcp.md +595 -0
- package/augment-extensions/domain-rules/mcp/rules/configuration.md +345 -0
- package/augment-extensions/domain-rules/mcp/rules/graph-augmented-mcp.md +687 -0
- package/augment-extensions/domain-rules/mcp/rules/hybrid-mcp.md +636 -0
- package/augment-extensions/domain-rules/mcp/rules/state-based-mcp.md +484 -0
- package/augment-extensions/domain-rules/mcp/rules/testing-validation.md +360 -0
- package/augment-extensions/domain-rules/mcp/rules/token-based-mcp.md +393 -0
- package/augment-extensions/domain-rules/mcp/rules/universal-rules.md +194 -0
- package/augment-extensions/domain-rules/mcp/rules/vector-based-mcp.md +625 -0
- package/augment-extensions/domain-rules/wordpress/README.md +163 -0
- package/augment-extensions/domain-rules/wordpress/module.json +32 -0
- package/augment-extensions/domain-rules/wordpress/rules/coding-standards.md +617 -0
- package/augment-extensions/domain-rules/wordpress/rules/directory-structure.md +270 -0
- package/augment-extensions/domain-rules/wordpress/rules/file-patterns.md +423 -0
- package/augment-extensions/domain-rules/wordpress/rules/gutenberg-blocks.md +493 -0
- package/augment-extensions/domain-rules/wordpress/rules/performance.md +568 -0
- package/augment-extensions/domain-rules/wordpress/rules/plugin-development.md +510 -0
- package/augment-extensions/domain-rules/wordpress/rules/project-detection.md +251 -0
- package/augment-extensions/domain-rules/wordpress/rules/rest-api.md +501 -0
- package/augment-extensions/domain-rules/wordpress/rules/security.md +564 -0
- package/augment-extensions/domain-rules/wordpress/rules/theme-development.md +388 -0
- package/augment-extensions/domain-rules/wordpress/rules/woocommerce.md +441 -0
- package/augment-extensions/domain-rules/wordpress-plugin/README.md +139 -0
- package/augment-extensions/domain-rules/wordpress-plugin/examples/ajax-plugin.md +1599 -0
- package/augment-extensions/domain-rules/wordpress-plugin/examples/custom-post-type-plugin.md +1727 -0
- package/augment-extensions/domain-rules/wordpress-plugin/examples/gutenberg-block-plugin.md +428 -0
- package/augment-extensions/domain-rules/wordpress-plugin/examples/gutenberg-block.md +422 -0
- package/augment-extensions/domain-rules/wordpress-plugin/examples/mvc-plugin.md +1623 -0
- package/augment-extensions/domain-rules/wordpress-plugin/examples/object-oriented-plugin.md +1343 -0
- package/augment-extensions/domain-rules/wordpress-plugin/examples/rest-endpoint.md +734 -0
- package/augment-extensions/domain-rules/wordpress-plugin/examples/settings-page-plugin.md +1350 -0
- package/augment-extensions/domain-rules/wordpress-plugin/examples/simple-procedural-plugin.md +503 -0
- package/augment-extensions/domain-rules/wordpress-plugin/examples/singleton-plugin.md +971 -0
- package/augment-extensions/domain-rules/wordpress-plugin/module.json +53 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/activation-hooks.md +770 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/admin-interface.md +874 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/ajax-handlers.md +629 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/asset-management.md +559 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/context-providers.md +709 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/cron-jobs.md +736 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/database-management.md +1057 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/documentation-standards.md +463 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/frontend-functionality.md +478 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/gutenberg-blocks.md +818 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/internationalization.md +416 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/migration.md +667 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/performance-optimization.md +878 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/plugin-architecture.md +693 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/plugin-structure.md +352 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/rest-api.md +818 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/scaffolding-workflow.md +624 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/security-best-practices.md +866 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/testing-patterns.md +1165 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/testing.md +414 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/vscode-integration.md +751 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/woocommerce-integration.md +949 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/wordpress-org-submission.md +458 -0
- package/augment-extensions/examples/gutenberg-block-plugin/README.md +101 -0
- package/augment-extensions/examples/gutenberg-block-plugin/examples/testimonial-block.md +428 -0
- package/augment-extensions/examples/gutenberg-block-plugin/module.json +40 -0
- package/augment-extensions/examples/rest-api-plugin/README.md +98 -0
- package/augment-extensions/examples/rest-api-plugin/examples/task-manager-api.md +1299 -0
- package/augment-extensions/examples/rest-api-plugin/module.json +40 -0
- package/augment-extensions/examples/woocommerce-extension/README.md +98 -0
- package/augment-extensions/examples/woocommerce-extension/examples/product-customizer.md +763 -0
- package/augment-extensions/examples/woocommerce-extension/module.json +40 -0
- package/augment-extensions/workflows/beads/module.json +4 -3
- package/augment-extensions/workflows/database/README.md +195 -0
- package/augment-extensions/workflows/database/ai-prompt-testing.md +295 -0
- package/augment-extensions/workflows/database/examples/migration-example.md +498 -0
- package/augment-extensions/workflows/database/examples/optimization-example.md +496 -0
- package/augment-extensions/workflows/database/examples/schema-design-example.md +444 -0
- package/augment-extensions/workflows/database/module.json +42 -0
- package/augment-extensions/workflows/database/rules/data-migration.md +249 -0
- package/augment-extensions/workflows/database/rules/documentation-standards.md +339 -0
- package/augment-extensions/workflows/database/rules/migration-workflow.md +352 -0
- package/augment-extensions/workflows/database/rules/optimization-workflow.md +435 -0
- package/augment-extensions/workflows/database/rules/schema-design-workflow.md +535 -0
- package/augment-extensions/workflows/database/rules/testing-patterns.md +305 -0
- package/augment-extensions/workflows/database/rules/workflow.md +458 -0
- package/augment-extensions/workflows/openspec/module.json +4 -3
- package/augment-extensions/workflows/wordpress-plugin/README.md +232 -0
- package/augment-extensions/workflows/wordpress-plugin/ai-prompts.md +839 -0
- package/augment-extensions/workflows/wordpress-plugin/bead-decomposition-patterns.md +854 -0
- package/augment-extensions/workflows/wordpress-plugin/examples/complete-plugin-example.md +540 -0
- package/augment-extensions/workflows/wordpress-plugin/examples/custom-post-type-example.md +1083 -0
- package/augment-extensions/workflows/wordpress-plugin/examples/feature-addition-workflow.md +669 -0
- package/augment-extensions/workflows/wordpress-plugin/examples/plugin-creation-workflow.md +597 -0
- package/augment-extensions/workflows/wordpress-plugin/examples/secure-form-handler-example.md +925 -0
- package/augment-extensions/workflows/wordpress-plugin/examples/security-audit-workflow.md +752 -0
- package/augment-extensions/workflows/wordpress-plugin/examples/wordpress-org-submission-workflow.md +773 -0
- package/augment-extensions/workflows/wordpress-plugin/module.json +49 -0
- package/augment-extensions/workflows/wordpress-plugin/rules/best-practices.md +942 -0
- package/augment-extensions/workflows/wordpress-plugin/rules/development-workflow.md +702 -0
- package/augment-extensions/workflows/wordpress-plugin/rules/submission-workflow.md +728 -0
- package/augment-extensions/workflows/wordpress-plugin/rules/testing-workflow.md +775 -0
- package/augment-extensions/writing-standards/screenplay/README.md +171 -0
- package/augment-extensions/writing-standards/screenplay/examples/aaa-hollywood-scene.fountain +164 -0
- package/augment-extensions/writing-standards/screenplay/module.json +124 -0
- package/augment-extensions/writing-standards/screenplay/rules/universal-formatting.md +339 -0
- package/cli/MODULES.md +302 -0
- package/cli/dist/cli.js +142 -9
- package/cli/dist/cli.js.map +1 -1
- package/cli/dist/commands/catalog.d.ts +13 -0
- package/cli/dist/commands/catalog.d.ts.map +1 -0
- package/cli/dist/commands/catalog.js +104 -0
- package/cli/dist/commands/catalog.js.map +1 -0
- package/cli/dist/commands/gui.d.ts +6 -0
- package/cli/dist/commands/gui.d.ts.map +1 -0
- package/cli/dist/commands/gui.js +211 -0
- package/cli/dist/commands/gui.js.map +1 -0
- package/cli/dist/commands/init.d.ts.map +1 -1
- package/cli/dist/commands/init.js +12 -0
- package/cli/dist/commands/init.js.map +1 -1
- package/cli/dist/commands/install-rules.d.ts +14 -0
- package/cli/dist/commands/install-rules.d.ts.map +1 -0
- package/cli/dist/commands/install-rules.js +127 -0
- package/cli/dist/commands/install-rules.js.map +1 -0
- package/cli/dist/commands/link.d.ts.map +1 -1
- package/cli/dist/commands/link.js +9 -11
- package/cli/dist/commands/link.js.map +1 -1
- package/cli/dist/commands/list.d.ts.map +1 -1
- package/cli/dist/commands/list.js +11 -28
- package/cli/dist/commands/list.js.map +1 -1
- package/cli/dist/commands/mcp.d.ts +48 -0
- package/cli/dist/commands/mcp.d.ts.map +1 -0
- package/cli/dist/commands/mcp.js +229 -0
- package/cli/dist/commands/mcp.js.map +1 -0
- package/cli/dist/commands/self-remove.d.ts +7 -0
- package/cli/dist/commands/self-remove.d.ts.map +1 -0
- package/cli/dist/commands/self-remove.js +179 -0
- package/cli/dist/commands/self-remove.js.map +1 -0
- package/cli/dist/commands/show.d.ts.map +1 -1
- package/cli/dist/commands/show.js +42 -71
- package/cli/dist/commands/show.js.map +1 -1
- package/cli/dist/commands/skill.d.ts +67 -0
- package/cli/dist/commands/skill.d.ts.map +1 -0
- package/cli/dist/commands/skill.js +513 -0
- package/cli/dist/commands/skill.js.map +1 -0
- package/cli/dist/commands/unlink.d.ts +6 -0
- package/cli/dist/commands/unlink.d.ts.map +1 -0
- package/cli/dist/commands/unlink.js +115 -0
- package/cli/dist/commands/unlink.js.map +1 -0
- package/cli/dist/commands/validate.d.ts +6 -0
- package/cli/dist/commands/validate.d.ts.map +1 -0
- package/cli/dist/commands/validate.js +159 -0
- package/cli/dist/commands/validate.js.map +1 -0
- package/cli/dist/utils/catalog-sync.d.ts +22 -0
- package/cli/dist/utils/catalog-sync.d.ts.map +1 -0
- package/cli/dist/utils/catalog-sync.js +157 -0
- package/cli/dist/utils/catalog-sync.js.map +1 -0
- package/cli/dist/utils/character-count.d.ts +56 -0
- package/cli/dist/utils/character-count.d.ts.map +1 -0
- package/cli/dist/utils/character-count.js +190 -0
- package/cli/dist/utils/character-count.js.map +1 -0
- package/cli/dist/utils/documentation-validator.d.ts +18 -0
- package/cli/dist/utils/documentation-validator.d.ts.map +1 -0
- package/cli/dist/utils/documentation-validator.js +233 -0
- package/cli/dist/utils/documentation-validator.js.map +1 -0
- package/cli/dist/utils/install-rules.d.ts +32 -0
- package/cli/dist/utils/install-rules.d.ts.map +1 -0
- package/cli/dist/utils/install-rules.js +375 -0
- package/cli/dist/utils/install-rules.js.map +1 -0
- package/cli/dist/utils/mcp-integration.d.ts +70 -0
- package/cli/dist/utils/mcp-integration.d.ts.map +1 -0
- package/cli/dist/utils/mcp-integration.js +292 -0
- package/cli/dist/utils/mcp-integration.js.map +1 -0
- package/cli/dist/utils/module-system.d.ts +153 -0
- package/cli/dist/utils/module-system.d.ts.map +1 -0
- package/cli/dist/utils/module-system.js +528 -0
- package/cli/dist/utils/module-system.js.map +1 -0
- package/cli/dist/utils/modules-catalog.d.ts +33 -0
- package/cli/dist/utils/modules-catalog.d.ts.map +1 -0
- package/cli/dist/utils/modules-catalog.js +163 -0
- package/cli/dist/utils/modules-catalog.js.map +1 -0
- package/cli/dist/utils/rule-install-hooks.d.ts +19 -0
- package/cli/dist/utils/rule-install-hooks.d.ts.map +1 -0
- package/cli/dist/utils/rule-install-hooks.js +224 -0
- package/cli/dist/utils/rule-install-hooks.js.map +1 -0
- package/cli/dist/utils/skill-system.d.ts +95 -0
- package/cli/dist/utils/skill-system.d.ts.map +1 -0
- package/cli/dist/utils/skill-system.js +313 -0
- package/cli/dist/utils/skill-system.js.map +1 -0
- package/modules.md +534 -70
- package/package.json +12 -3
|
@@ -0,0 +1,1076 @@
|
|
|
1
|
+
# Database Performance Optimization
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
This document covers comprehensive performance optimization strategies for databases, including indexing, query optimization, connection pooling, caching, batch operations, and monitoring.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Indexing Strategies
|
|
10
|
+
|
|
11
|
+
### When to Create Indexes
|
|
12
|
+
|
|
13
|
+
**Create indexes for:**
|
|
14
|
+
- ✅ Primary keys (automatic in most databases)
|
|
15
|
+
- ✅ Foreign keys
|
|
16
|
+
- ✅ Columns used in WHERE clauses
|
|
17
|
+
- ✅ Columns used in JOIN conditions
|
|
18
|
+
- ✅ Columns used in ORDER BY clauses
|
|
19
|
+
- ✅ Columns used in GROUP BY clauses
|
|
20
|
+
- ✅ Columns with high cardinality (many unique values)
|
|
21
|
+
|
|
22
|
+
**Avoid indexes for:**
|
|
23
|
+
- ❌ Small tables (< 1000 rows)
|
|
24
|
+
- ❌ Columns with low cardinality (few unique values)
|
|
25
|
+
- ❌ Columns that are frequently updated
|
|
26
|
+
- ❌ Tables with high write-to-read ratio
|
|
27
|
+
|
|
28
|
+
### Index Types
|
|
29
|
+
|
|
30
|
+
#### B-Tree Indexes (Default)
|
|
31
|
+
|
|
32
|
+
**Best for:** Equality and range queries
|
|
33
|
+
|
|
34
|
+
```sql
|
|
35
|
+
-- PostgreSQL: Create B-tree index
|
|
36
|
+
CREATE INDEX idx_users_email ON users(email);
|
|
37
|
+
CREATE INDEX idx_orders_created_at ON orders(created_at);
|
|
38
|
+
|
|
39
|
+
-- Range query benefits from B-tree index
|
|
40
|
+
SELECT * FROM orders
|
|
41
|
+
WHERE created_at BETWEEN '2024-01-01' AND '2024-12-31';
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
#### Hash Indexes
|
|
45
|
+
|
|
46
|
+
**Best for:** Equality comparisons only
|
|
47
|
+
|
|
48
|
+
```sql
|
|
49
|
+
-- PostgreSQL: Create hash index
|
|
50
|
+
CREATE INDEX idx_users_email_hash ON users USING HASH(email);
|
|
51
|
+
|
|
52
|
+
-- Equality query benefits from hash index
|
|
53
|
+
SELECT * FROM users WHERE email = 'user@example.com';
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
#### Composite Indexes
|
|
57
|
+
|
|
58
|
+
**Best for:** Queries filtering on multiple columns
|
|
59
|
+
|
|
60
|
+
```sql
|
|
61
|
+
-- Create composite index
|
|
62
|
+
CREATE INDEX idx_orders_user_status ON orders(user_id, status);
|
|
63
|
+
|
|
64
|
+
-- Query benefits from composite index
|
|
65
|
+
SELECT * FROM orders
|
|
66
|
+
WHERE user_id = 123 AND status = 'pending';
|
|
67
|
+
|
|
68
|
+
-- Query partially benefits (uses user_id only)
|
|
69
|
+
SELECT * FROM orders WHERE user_id = 123;
|
|
70
|
+
|
|
71
|
+
-- Query does NOT benefit (status is not leftmost column)
|
|
72
|
+
SELECT * FROM orders WHERE status = 'pending';
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
**Index Column Order:**
|
|
76
|
+
- Put most selective column first
|
|
77
|
+
- Put columns used in equality comparisons before range comparisons
|
|
78
|
+
- Consider query patterns
|
|
79
|
+
|
|
80
|
+
#### Covering Indexes
|
|
81
|
+
|
|
82
|
+
**Include all columns needed by query:**
|
|
83
|
+
|
|
84
|
+
```sql
|
|
85
|
+
-- PostgreSQL: Create covering index
|
|
86
|
+
CREATE INDEX idx_users_email_covering ON users(email) INCLUDE (name, created_at);
|
|
87
|
+
|
|
88
|
+
-- Query uses index-only scan (no table access needed)
|
|
89
|
+
SELECT name, created_at FROM users WHERE email = 'user@example.com';
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
#### Partial Indexes
|
|
93
|
+
|
|
94
|
+
**Index only subset of rows:**
|
|
95
|
+
|
|
96
|
+
```sql
|
|
97
|
+
-- PostgreSQL: Create partial index
|
|
98
|
+
CREATE INDEX idx_orders_pending ON orders(created_at)
|
|
99
|
+
WHERE status = 'pending';
|
|
100
|
+
|
|
101
|
+
-- Query benefits from smaller, more efficient index
|
|
102
|
+
SELECT * FROM orders
|
|
103
|
+
WHERE status = 'pending' AND created_at > '2024-01-01';
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
#### Full-Text Search Indexes
|
|
107
|
+
|
|
108
|
+
**Best for:** Text search queries
|
|
109
|
+
|
|
110
|
+
```sql
|
|
111
|
+
-- PostgreSQL: Create GIN index for full-text search
|
|
112
|
+
CREATE INDEX idx_articles_content_fts ON articles
|
|
113
|
+
USING GIN(to_tsvector('english', content));
|
|
114
|
+
|
|
115
|
+
-- Full-text search query
|
|
116
|
+
SELECT * FROM articles
|
|
117
|
+
WHERE to_tsvector('english', content) @@ to_tsquery('english', 'database & optimization');
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### Index Maintenance
|
|
121
|
+
|
|
122
|
+
```sql
|
|
123
|
+
-- PostgreSQL: Analyze index usage
|
|
124
|
+
SELECT
|
|
125
|
+
schemaname,
|
|
126
|
+
tablename,
|
|
127
|
+
indexname,
|
|
128
|
+
idx_scan,
|
|
129
|
+
idx_tup_read,
|
|
130
|
+
idx_tup_fetch
|
|
131
|
+
FROM pg_stat_user_indexes
|
|
132
|
+
ORDER BY idx_scan ASC;
|
|
133
|
+
|
|
134
|
+
-- Find unused indexes
|
|
135
|
+
SELECT
|
|
136
|
+
schemaname,
|
|
137
|
+
tablename,
|
|
138
|
+
indexname
|
|
139
|
+
FROM pg_stat_user_indexes
|
|
140
|
+
WHERE idx_scan = 0
|
|
141
|
+
AND indexname NOT LIKE 'pg_toast%';
|
|
142
|
+
|
|
143
|
+
-- Rebuild index to reduce bloat
|
|
144
|
+
REINDEX INDEX idx_users_email;
|
|
145
|
+
|
|
146
|
+
-- Rebuild all indexes on table
|
|
147
|
+
REINDEX TABLE users;
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
---
|
|
151
|
+
|
|
152
|
+
## Query Optimization
|
|
153
|
+
|
|
154
|
+
### Analyze Query Execution Plans
|
|
155
|
+
|
|
156
|
+
```sql
|
|
157
|
+
-- PostgreSQL: Explain query execution plan
|
|
158
|
+
EXPLAIN ANALYZE
|
|
159
|
+
SELECT u.name, COUNT(o.id) AS order_count
|
|
160
|
+
FROM users u
|
|
161
|
+
LEFT JOIN orders o ON o.user_id = u.id
|
|
162
|
+
WHERE u.created_at > '2024-01-01'
|
|
163
|
+
GROUP BY u.id, u.name
|
|
164
|
+
ORDER BY order_count DESC
|
|
165
|
+
LIMIT 10;
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
**Key metrics to look for:**
|
|
169
|
+
- **Seq Scan**: Table scan (slow for large tables)
|
|
170
|
+
- **Index Scan**: Using index (fast)
|
|
171
|
+
- **Index Only Scan**: Using covering index (fastest)
|
|
172
|
+
- **Nested Loop**: Join method (good for small datasets)
|
|
173
|
+
- **Hash Join**: Join method (good for large datasets)
|
|
174
|
+
- **Merge Join**: Join method (good for sorted data)
|
|
175
|
+
|
|
176
|
+
### Optimize SELECT Queries
|
|
177
|
+
|
|
178
|
+
```sql
|
|
179
|
+
-- ❌ BAD: Select all columns
|
|
180
|
+
SELECT * FROM users;
|
|
181
|
+
|
|
182
|
+
-- ✅ GOOD: Select only needed columns
|
|
183
|
+
SELECT id, email, name FROM users;
|
|
184
|
+
|
|
185
|
+
-- ❌ BAD: No LIMIT on large result set
|
|
186
|
+
SELECT * FROM orders ORDER BY created_at DESC;
|
|
187
|
+
|
|
188
|
+
-- ✅ GOOD: Use LIMIT for pagination
|
|
189
|
+
SELECT * FROM orders ORDER BY created_at DESC LIMIT 20 OFFSET 0;
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
### Optimize WHERE Clauses
|
|
193
|
+
|
|
194
|
+
```sql
|
|
195
|
+
-- ❌ BAD: Function on indexed column prevents index usage
|
|
196
|
+
SELECT * FROM users WHERE LOWER(email) = 'user@example.com';
|
|
197
|
+
|
|
198
|
+
-- ✅ GOOD: Use functional index or case-insensitive collation
|
|
199
|
+
CREATE INDEX idx_users_email_lower ON users(LOWER(email));
|
|
200
|
+
SELECT * FROM users WHERE LOWER(email) = 'user@example.com';
|
|
201
|
+
|
|
202
|
+
-- ❌ BAD: Leading wildcard prevents index usage
|
|
203
|
+
SELECT * FROM users WHERE email LIKE '%@example.com';
|
|
204
|
+
|
|
205
|
+
-- ✅ GOOD: No leading wildcard allows index usage
|
|
206
|
+
SELECT * FROM users WHERE email LIKE 'user@%';
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
### Optimize JOIN Queries
|
|
210
|
+
|
|
211
|
+
```sql
|
|
212
|
+
-- ❌ BAD: Cartesian product (no join condition)
|
|
213
|
+
SELECT * FROM users, orders;
|
|
214
|
+
|
|
215
|
+
-- ✅ GOOD: Proper join condition
|
|
216
|
+
SELECT * FROM users u
|
|
217
|
+
INNER JOIN orders o ON o.user_id = u.id;
|
|
218
|
+
|
|
219
|
+
-- ❌ BAD: Subquery in SELECT (N+1 problem)
|
|
220
|
+
SELECT
|
|
221
|
+
u.id,
|
|
222
|
+
u.name,
|
|
223
|
+
(SELECT COUNT(*) FROM orders WHERE user_id = u.id) AS order_count
|
|
224
|
+
FROM users u;
|
|
225
|
+
|
|
226
|
+
-- ✅ GOOD: Use JOIN with aggregation
|
|
227
|
+
SELECT
|
|
228
|
+
u.id,
|
|
229
|
+
u.name,
|
|
230
|
+
COUNT(o.id) AS order_count
|
|
231
|
+
FROM users u
|
|
232
|
+
LEFT JOIN orders o ON o.user_id = u.id
|
|
233
|
+
GROUP BY u.id, u.name;
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
### Avoid N+1 Queries
|
|
237
|
+
|
|
238
|
+
```javascript
|
|
239
|
+
// ❌ BAD: N+1 query problem
|
|
240
|
+
async function getUsersWithOrders() {
|
|
241
|
+
const users = await db.query('SELECT * FROM users');
|
|
242
|
+
|
|
243
|
+
for (const user of users.rows) {
|
|
244
|
+
// This executes N queries (one per user)
|
|
245
|
+
const orders = await db.query('SELECT * FROM orders WHERE user_id = $1', [user.id]);
|
|
246
|
+
user.orders = orders.rows;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
return users.rows;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
// ✅ GOOD: Single query with JOIN
|
|
253
|
+
async function getUsersWithOrders() {
|
|
254
|
+
const result = await db.query(`
|
|
255
|
+
SELECT
|
|
256
|
+
u.id,
|
|
257
|
+
u.name,
|
|
258
|
+
u.email,
|
|
259
|
+
json_agg(
|
|
260
|
+
json_build_object(
|
|
261
|
+
'id', o.id,
|
|
262
|
+
'total', o.total,
|
|
263
|
+
'created_at', o.created_at
|
|
264
|
+
)
|
|
265
|
+
) AS orders
|
|
266
|
+
FROM users u
|
|
267
|
+
LEFT JOIN orders o ON o.user_id = u.id
|
|
268
|
+
GROUP BY u.id, u.name, u.email
|
|
269
|
+
`);
|
|
270
|
+
|
|
271
|
+
return result.rows;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
// ✅ GOOD: Two queries (better for large datasets)
|
|
275
|
+
async function getUsersWithOrders() {
|
|
276
|
+
const users = await db.query('SELECT * FROM users');
|
|
277
|
+
const userIds = users.rows.map(u => u.id);
|
|
278
|
+
|
|
279
|
+
const orders = await db.query(
|
|
280
|
+
'SELECT * FROM orders WHERE user_id = ANY($1)',
|
|
281
|
+
[userIds]
|
|
282
|
+
);
|
|
283
|
+
|
|
284
|
+
// Group orders by user_id in application
|
|
285
|
+
const ordersByUser = orders.rows.reduce((acc, order) => {
|
|
286
|
+
if (!acc[order.user_id]) acc[order.user_id] = [];
|
|
287
|
+
acc[order.user_id].push(order);
|
|
288
|
+
return acc;
|
|
289
|
+
}, {});
|
|
290
|
+
|
|
291
|
+
users.rows.forEach(user => {
|
|
292
|
+
user.orders = ordersByUser[user.id] || [];
|
|
293
|
+
});
|
|
294
|
+
|
|
295
|
+
return users.rows;
|
|
296
|
+
}
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
---
|
|
300
|
+
|
|
301
|
+
## Connection Pooling
|
|
302
|
+
|
|
303
|
+
### Why Connection Pooling?
|
|
304
|
+
|
|
305
|
+
**Benefits:**
|
|
306
|
+
- ✅ Reuse existing connections (avoid connection overhead)
|
|
307
|
+
- ✅ Limit concurrent connections to database
|
|
308
|
+
- ✅ Improve application performance
|
|
309
|
+
- ✅ Prevent connection exhaustion
|
|
310
|
+
|
|
311
|
+
### Connection Pool Configuration
|
|
312
|
+
|
|
313
|
+
```javascript
|
|
314
|
+
// Node.js with pg (PostgreSQL)
|
|
315
|
+
const { Pool } = require('pg');
|
|
316
|
+
|
|
317
|
+
const pool = new Pool({
|
|
318
|
+
host: process.env.DB_HOST,
|
|
319
|
+
database: process.env.DB_NAME,
|
|
320
|
+
user: process.env.DB_USER,
|
|
321
|
+
password: process.env.DB_PASSWORD,
|
|
322
|
+
|
|
323
|
+
// Connection pool settings
|
|
324
|
+
max: 20, // Maximum connections in pool
|
|
325
|
+
min: 5, // Minimum connections in pool
|
|
326
|
+
idleTimeoutMillis: 30000, // Close idle connections after 30s
|
|
327
|
+
connectionTimeoutMillis: 2000, // Wait 2s for available connection
|
|
328
|
+
|
|
329
|
+
// Keep-alive settings
|
|
330
|
+
keepAlive: true,
|
|
331
|
+
keepAliveInitialDelayMillis: 10000
|
|
332
|
+
});
|
|
333
|
+
|
|
334
|
+
// Use pool for queries
|
|
335
|
+
async function getUser(userId) {
|
|
336
|
+
const result = await pool.query('SELECT * FROM users WHERE id = $1', [userId]);
|
|
337
|
+
return result.rows[0];
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
// Graceful shutdown
|
|
341
|
+
process.on('SIGTERM', async () => {
|
|
342
|
+
await pool.end();
|
|
343
|
+
process.exit(0);
|
|
344
|
+
});
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
```python
|
|
348
|
+
# Python with psycopg2 (PostgreSQL)
|
|
349
|
+
import psycopg2
|
|
350
|
+
from psycopg2 import pool
|
|
351
|
+
|
|
352
|
+
# Create connection pool
|
|
353
|
+
connection_pool = psycopg2.pool.ThreadedConnectionPool(
|
|
354
|
+
minconn=5,
|
|
355
|
+
maxconn=20,
|
|
356
|
+
host=os.environ['DB_HOST'],
|
|
357
|
+
database=os.environ['DB_NAME'],
|
|
358
|
+
user=os.environ['DB_USER'],
|
|
359
|
+
password=os.environ['DB_PASSWORD']
|
|
360
|
+
)
|
|
361
|
+
|
|
362
|
+
# Use connection from pool
|
|
363
|
+
def get_user(user_id):
|
|
364
|
+
conn = connection_pool.getconn()
|
|
365
|
+
try:
|
|
366
|
+
cursor = conn.cursor()
|
|
367
|
+
cursor.execute('SELECT * FROM users WHERE id = %s', (user_id,))
|
|
368
|
+
return cursor.fetchone()
|
|
369
|
+
finally:
|
|
370
|
+
connection_pool.putconn(conn)
|
|
371
|
+
```
|
|
372
|
+
|
|
373
|
+
### Connection Pool Best Practices
|
|
374
|
+
|
|
375
|
+
✅ **DO:**
|
|
376
|
+
- Set appropriate pool size (start with 10-20 connections)
|
|
377
|
+
- Monitor pool utilization
|
|
378
|
+
- Use connection timeouts
|
|
379
|
+
- Implement graceful shutdown
|
|
380
|
+
- Return connections to pool after use
|
|
381
|
+
|
|
382
|
+
❌ **DON'T:**
|
|
383
|
+
- Create new pool for each request
|
|
384
|
+
- Set pool size too high (wastes resources)
|
|
385
|
+
- Set pool size too low (causes bottlenecks)
|
|
386
|
+
- Forget to release connections
|
|
387
|
+
|
|
388
|
+
---
|
|
389
|
+
|
|
390
|
+
## Caching Strategies
|
|
391
|
+
|
|
392
|
+
### Application-Level Caching
|
|
393
|
+
|
|
394
|
+
```javascript
|
|
395
|
+
// Redis caching example
|
|
396
|
+
const redis = require('redis');
|
|
397
|
+
const client = redis.createClient();
|
|
398
|
+
|
|
399
|
+
async function getUser(userId) {
|
|
400
|
+
const cacheKey = `user:${userId}`;
|
|
401
|
+
|
|
402
|
+
// Try cache first
|
|
403
|
+
const cached = await client.get(cacheKey);
|
|
404
|
+
if (cached) {
|
|
405
|
+
return JSON.parse(cached);
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
// Cache miss: query database
|
|
409
|
+
const result = await db.query('SELECT * FROM users WHERE id = $1', [userId]);
|
|
410
|
+
const user = result.rows[0];
|
|
411
|
+
|
|
412
|
+
// Store in cache (TTL: 1 hour)
|
|
413
|
+
await client.setEx(cacheKey, 3600, JSON.stringify(user));
|
|
414
|
+
|
|
415
|
+
return user;
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
// Invalidate cache on update
|
|
419
|
+
async function updateUser(userId, updates) {
|
|
420
|
+
await db.query(
|
|
421
|
+
'UPDATE users SET name = $1, email = $2 WHERE id = $3',
|
|
422
|
+
[updates.name, updates.email, userId]
|
|
423
|
+
);
|
|
424
|
+
|
|
425
|
+
// Invalidate cache
|
|
426
|
+
await client.del(`user:${userId}`);
|
|
427
|
+
}
|
|
428
|
+
```
|
|
429
|
+
|
|
430
|
+
### Query Result Caching
|
|
431
|
+
|
|
432
|
+
```javascript
|
|
433
|
+
// Cache expensive query results
|
|
434
|
+
async function getTopProducts() {
|
|
435
|
+
const cacheKey = 'top_products';
|
|
436
|
+
|
|
437
|
+
const cached = await client.get(cacheKey);
|
|
438
|
+
if (cached) {
|
|
439
|
+
return JSON.parse(cached);
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
const result = await db.query(`
|
|
443
|
+
SELECT
|
|
444
|
+
p.id,
|
|
445
|
+
p.name,
|
|
446
|
+
COUNT(oi.id) AS sales_count,
|
|
447
|
+
SUM(oi.quantity * oi.price) AS total_revenue
|
|
448
|
+
FROM products p
|
|
449
|
+
JOIN order_items oi ON oi.product_id = p.id
|
|
450
|
+
WHERE oi.created_at > NOW() - INTERVAL '30 days'
|
|
451
|
+
GROUP BY p.id, p.name
|
|
452
|
+
ORDER BY sales_count DESC
|
|
453
|
+
LIMIT 10
|
|
454
|
+
`);
|
|
455
|
+
|
|
456
|
+
// Cache for 15 minutes
|
|
457
|
+
await client.setEx(cacheKey, 900, JSON.stringify(result.rows));
|
|
458
|
+
|
|
459
|
+
return result.rows;
|
|
460
|
+
}
|
|
461
|
+
```
|
|
462
|
+
|
|
463
|
+
### Database-Level Caching
|
|
464
|
+
|
|
465
|
+
```sql
|
|
466
|
+
-- PostgreSQL: Increase shared_buffers for better caching
|
|
467
|
+
-- In postgresql.conf:
|
|
468
|
+
-- shared_buffers = 256MB (25% of RAM for dedicated DB server)
|
|
469
|
+
-- effective_cache_size = 1GB (50-75% of RAM)
|
|
470
|
+
|
|
471
|
+
-- Monitor cache hit ratio
|
|
472
|
+
SELECT
|
|
473
|
+
sum(heap_blks_read) AS heap_read,
|
|
474
|
+
sum(heap_blks_hit) AS heap_hit,
|
|
475
|
+
sum(heap_blks_hit) / (sum(heap_blks_hit) + sum(heap_blks_read)) AS cache_hit_ratio
|
|
476
|
+
FROM pg_statio_user_tables;
|
|
477
|
+
-- Target: > 0.99 (99% cache hit ratio)
|
|
478
|
+
```
|
|
479
|
+
|
|
480
|
+
### Caching Best Practices
|
|
481
|
+
|
|
482
|
+
✅ **DO:**
|
|
483
|
+
- Cache frequently accessed data
|
|
484
|
+
- Set appropriate TTL (time-to-live)
|
|
485
|
+
- Invalidate cache on updates
|
|
486
|
+
- Monitor cache hit ratio
|
|
487
|
+
- Use cache for expensive queries
|
|
488
|
+
|
|
489
|
+
❌ **DON'T:**
|
|
490
|
+
- Cache everything (wastes memory)
|
|
491
|
+
- Set TTL too long (stale data)
|
|
492
|
+
- Set TTL too short (cache thrashing)
|
|
493
|
+
- Forget to invalidate cache on updates
|
|
494
|
+
|
|
495
|
+
---
|
|
496
|
+
|
|
497
|
+
## Batch Operations
|
|
498
|
+
|
|
499
|
+
### Batch Inserts
|
|
500
|
+
|
|
501
|
+
```javascript
|
|
502
|
+
// ❌ BAD: Individual inserts
|
|
503
|
+
async function createUsers(users) {
|
|
504
|
+
for (const user of users) {
|
|
505
|
+
await db.query(
|
|
506
|
+
'INSERT INTO users (name, email) VALUES ($1, $2)',
|
|
507
|
+
[user.name, user.email]
|
|
508
|
+
);
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
// ✅ GOOD: Batch insert
|
|
513
|
+
async function createUsers(users) {
|
|
514
|
+
const values = users.map((user, i) =>
|
|
515
|
+
`($${i * 2 + 1}, $${i * 2 + 2})`
|
|
516
|
+
).join(', ');
|
|
517
|
+
|
|
518
|
+
const params = users.flatMap(user => [user.name, user.email]);
|
|
519
|
+
|
|
520
|
+
await db.query(
|
|
521
|
+
`INSERT INTO users (name, email) VALUES ${values}`,
|
|
522
|
+
params
|
|
523
|
+
);
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
// ✅ BETTER: Use COPY for large datasets (PostgreSQL)
|
|
527
|
+
const { from } = require('pg-copy-streams');
|
|
528
|
+
const fs = require('fs');
|
|
529
|
+
|
|
530
|
+
async function bulkInsertUsers(csvFilePath) {
|
|
531
|
+
const client = await pool.connect();
|
|
532
|
+
try {
|
|
533
|
+
const stream = client.query(
|
|
534
|
+
from('COPY users (name, email) FROM STDIN WITH CSV')
|
|
535
|
+
);
|
|
536
|
+
const fileStream = fs.createReadStream(csvFilePath);
|
|
537
|
+
fileStream.pipe(stream);
|
|
538
|
+
|
|
539
|
+
await new Promise((resolve, reject) => {
|
|
540
|
+
stream.on('finish', resolve);
|
|
541
|
+
stream.on('error', reject);
|
|
542
|
+
});
|
|
543
|
+
} finally {
|
|
544
|
+
client.release();
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
```
|
|
548
|
+
|
|
549
|
+
### Batch Updates
|
|
550
|
+
|
|
551
|
+
```javascript
|
|
552
|
+
// ❌ BAD: Individual updates
|
|
553
|
+
async function updateUserStatuses(userIds, status) {
|
|
554
|
+
for (const userId of userIds) {
|
|
555
|
+
await db.query(
|
|
556
|
+
'UPDATE users SET status = $1 WHERE id = $2',
|
|
557
|
+
[status, userId]
|
|
558
|
+
);
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
// ✅ GOOD: Batch update
|
|
563
|
+
async function updateUserStatuses(userIds, status) {
|
|
564
|
+
await db.query(
|
|
565
|
+
'UPDATE users SET status = $1 WHERE id = ANY($2)',
|
|
566
|
+
[status, userIds]
|
|
567
|
+
);
|
|
568
|
+
}
|
|
569
|
+
```
|
|
570
|
+
|
|
571
|
+
### Batch Deletes
|
|
572
|
+
|
|
573
|
+
```javascript
|
|
574
|
+
// ❌ BAD: Individual deletes
|
|
575
|
+
async function deleteOrders(orderIds) {
|
|
576
|
+
for (const orderId of orderIds) {
|
|
577
|
+
await db.query('DELETE FROM orders WHERE id = $1', [orderId]);
|
|
578
|
+
}
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
// ✅ GOOD: Batch delete
|
|
582
|
+
async function deleteOrders(orderIds) {
|
|
583
|
+
await db.query('DELETE FROM orders WHERE id = ANY($1)', [orderIds]);
|
|
584
|
+
}
|
|
585
|
+
```
|
|
586
|
+
|
|
587
|
+
---
|
|
588
|
+
|
|
589
|
+
## Pagination
|
|
590
|
+
|
|
591
|
+
### Offset-Based Pagination
|
|
592
|
+
|
|
593
|
+
```sql
|
|
594
|
+
-- Simple but slow for large offsets
|
|
595
|
+
SELECT * FROM orders
|
|
596
|
+
ORDER BY created_at DESC
|
|
597
|
+
LIMIT 20 OFFSET 1000; -- Slow: database must scan 1020 rows
|
|
598
|
+
```
|
|
599
|
+
|
|
600
|
+
### Cursor-Based Pagination (Keyset Pagination)
|
|
601
|
+
|
|
602
|
+
```sql
|
|
603
|
+
-- Fast for any page
|
|
604
|
+
-- First page
|
|
605
|
+
SELECT * FROM orders
|
|
606
|
+
ORDER BY created_at DESC, id DESC
|
|
607
|
+
LIMIT 20;
|
|
608
|
+
|
|
609
|
+
-- Next page (using last item from previous page)
|
|
610
|
+
SELECT * FROM orders
|
|
611
|
+
WHERE (created_at, id) < ('2024-01-15 10:30:00', 12345)
|
|
612
|
+
ORDER BY created_at DESC, id DESC
|
|
613
|
+
LIMIT 20;
|
|
614
|
+
```
|
|
615
|
+
|
|
616
|
+
```javascript
|
|
617
|
+
// Cursor-based pagination implementation
|
|
618
|
+
async function getOrders(cursor = null, limit = 20) {
|
|
619
|
+
let query = 'SELECT * FROM orders';
|
|
620
|
+
let params = [limit];
|
|
621
|
+
|
|
622
|
+
if (cursor) {
|
|
623
|
+
const [createdAt, id] = cursor.split('_');
|
|
624
|
+
query += ' WHERE (created_at, id) < ($2, $3)';
|
|
625
|
+
params.push(createdAt, id);
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
query += ' ORDER BY created_at DESC, id DESC LIMIT $1';
|
|
629
|
+
|
|
630
|
+
const result = await db.query(query, params);
|
|
631
|
+
const orders = result.rows;
|
|
632
|
+
|
|
633
|
+
// Generate cursor for next page
|
|
634
|
+
const nextCursor = orders.length > 0
|
|
635
|
+
? `${orders[orders.length - 1].created_at}_${orders[orders.length - 1].id}`
|
|
636
|
+
: null;
|
|
637
|
+
|
|
638
|
+
return { orders, nextCursor };
|
|
639
|
+
}
|
|
640
|
+
```
|
|
641
|
+
|
|
642
|
+
---
|
|
643
|
+
|
|
644
|
+
## Denormalization
|
|
645
|
+
|
|
646
|
+
### When to Denormalize
|
|
647
|
+
|
|
648
|
+
**Consider denormalization when:**
|
|
649
|
+
- ✅ Read performance is critical
|
|
650
|
+
- ✅ Data is read much more than written
|
|
651
|
+
- ✅ Complex joins are causing performance issues
|
|
652
|
+
- ✅ Aggregations are expensive
|
|
653
|
+
|
|
654
|
+
**Avoid denormalization when:**
|
|
655
|
+
- ❌ Data changes frequently
|
|
656
|
+
- ❌ Data consistency is critical
|
|
657
|
+
- ❌ Storage space is limited
|
|
658
|
+
|
|
659
|
+
### Denormalization Strategies
|
|
660
|
+
|
|
661
|
+
#### Materialized Views
|
|
662
|
+
|
|
663
|
+
```sql
|
|
664
|
+
-- PostgreSQL: Create materialized view for expensive aggregation
|
|
665
|
+
CREATE MATERIALIZED VIEW user_order_stats AS
|
|
666
|
+
SELECT
|
|
667
|
+
u.id AS user_id,
|
|
668
|
+
u.name,
|
|
669
|
+
u.email,
|
|
670
|
+
COUNT(o.id) AS total_orders,
|
|
671
|
+
SUM(o.total) AS total_spent,
|
|
672
|
+
MAX(o.created_at) AS last_order_date
|
|
673
|
+
FROM users u
|
|
674
|
+
LEFT JOIN orders o ON o.user_id = u.id
|
|
675
|
+
GROUP BY u.id, u.name, u.email;
|
|
676
|
+
|
|
677
|
+
-- Create index on materialized view
|
|
678
|
+
CREATE INDEX idx_user_order_stats_user_id ON user_order_stats(user_id);
|
|
679
|
+
|
|
680
|
+
-- Refresh materialized view (run periodically)
|
|
681
|
+
REFRESH MATERIALIZED VIEW user_order_stats;
|
|
682
|
+
|
|
683
|
+
-- Query materialized view (fast)
|
|
684
|
+
SELECT * FROM user_order_stats WHERE user_id = 123;
|
|
685
|
+
```
|
|
686
|
+
|
|
687
|
+
#### Computed Columns
|
|
688
|
+
|
|
689
|
+
```sql
|
|
690
|
+
-- PostgreSQL: Add computed column
|
|
691
|
+
ALTER TABLE orders ADD COLUMN total_items INTEGER;
|
|
692
|
+
|
|
693
|
+
-- Update computed column with trigger
|
|
694
|
+
CREATE OR REPLACE FUNCTION update_order_total_items()
|
|
695
|
+
RETURNS TRIGGER AS $$
|
|
696
|
+
BEGIN
|
|
697
|
+
UPDATE orders
|
|
698
|
+
SET total_items = (
|
|
699
|
+
SELECT COUNT(*) FROM order_items WHERE order_id = NEW.order_id
|
|
700
|
+
)
|
|
701
|
+
WHERE id = NEW.order_id;
|
|
702
|
+
RETURN NEW;
|
|
703
|
+
END;
|
|
704
|
+
$$ LANGUAGE plpgsql;
|
|
705
|
+
|
|
706
|
+
CREATE TRIGGER update_order_total_items_trigger
|
|
707
|
+
AFTER INSERT OR DELETE ON order_items
|
|
708
|
+
FOR EACH ROW EXECUTE FUNCTION update_order_total_items();
|
|
709
|
+
```
|
|
710
|
+
|
|
711
|
+
#### Redundant Data
|
|
712
|
+
|
|
713
|
+
```sql
|
|
714
|
+
-- Store frequently accessed data redundantly
|
|
715
|
+
CREATE TABLE orders (
|
|
716
|
+
id SERIAL PRIMARY KEY,
|
|
717
|
+
user_id INTEGER NOT NULL,
|
|
718
|
+
user_email VARCHAR(255), -- Redundant: also in users table
|
|
719
|
+
user_name VARCHAR(255), -- Redundant: also in users table
|
|
720
|
+
total DECIMAL(10, 2),
|
|
721
|
+
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
722
|
+
);
|
|
723
|
+
|
|
724
|
+
-- Update redundant data with trigger
|
|
725
|
+
CREATE OR REPLACE FUNCTION sync_user_data_to_orders()
|
|
726
|
+
RETURNS TRIGGER AS $$
|
|
727
|
+
BEGIN
|
|
728
|
+
UPDATE orders
|
|
729
|
+
SET user_email = NEW.email, user_name = NEW.name
|
|
730
|
+
WHERE user_id = NEW.id;
|
|
731
|
+
RETURN NEW;
|
|
732
|
+
END;
|
|
733
|
+
$$ LANGUAGE plpgsql;
|
|
734
|
+
|
|
735
|
+
CREATE TRIGGER sync_user_data_trigger
|
|
736
|
+
AFTER UPDATE ON users
|
|
737
|
+
FOR EACH ROW EXECUTE FUNCTION sync_user_data_to_orders();
|
|
738
|
+
```
|
|
739
|
+
|
|
740
|
+
---
|
|
741
|
+
|
|
742
|
+
## Monitoring & Profiling
|
|
743
|
+
|
|
744
|
+
### Key Performance Metrics
|
|
745
|
+
|
|
746
|
+
```sql
|
|
747
|
+
-- PostgreSQL: Monitor slow queries
|
|
748
|
+
SELECT
|
|
749
|
+
query,
|
|
750
|
+
calls,
|
|
751
|
+
total_time,
|
|
752
|
+
mean_time,
|
|
753
|
+
max_time,
|
|
754
|
+
stddev_time
|
|
755
|
+
FROM pg_stat_statements
|
|
756
|
+
ORDER BY mean_time DESC
|
|
757
|
+
LIMIT 20;
|
|
758
|
+
|
|
759
|
+
-- Monitor table statistics
|
|
760
|
+
SELECT
|
|
761
|
+
schemaname,
|
|
762
|
+
tablename,
|
|
763
|
+
seq_scan,
|
|
764
|
+
seq_tup_read,
|
|
765
|
+
idx_scan,
|
|
766
|
+
idx_tup_fetch,
|
|
767
|
+
n_tup_ins,
|
|
768
|
+
n_tup_upd,
|
|
769
|
+
n_tup_del
|
|
770
|
+
FROM pg_stat_user_tables
|
|
771
|
+
ORDER BY seq_scan DESC;
|
|
772
|
+
|
|
773
|
+
-- Monitor index usage
|
|
774
|
+
SELECT
|
|
775
|
+
schemaname,
|
|
776
|
+
tablename,
|
|
777
|
+
indexname,
|
|
778
|
+
idx_scan,
|
|
779
|
+
idx_tup_read,
|
|
780
|
+
idx_tup_fetch
|
|
781
|
+
FROM pg_stat_user_indexes
|
|
782
|
+
ORDER BY idx_scan DESC;
|
|
783
|
+
|
|
784
|
+
-- Monitor database size
|
|
785
|
+
SELECT
|
|
786
|
+
pg_database.datname,
|
|
787
|
+
pg_size_pretty(pg_database_size(pg_database.datname)) AS size
|
|
788
|
+
FROM pg_database
|
|
789
|
+
ORDER BY pg_database_size(pg_database.datname) DESC;
|
|
790
|
+
|
|
791
|
+
-- Monitor table bloat
|
|
792
|
+
SELECT
|
|
793
|
+
schemaname,
|
|
794
|
+
tablename,
|
|
795
|
+
pg_size_pretty(pg_total_relation_size(schemaname||'.'||tablename)) AS size,
|
|
796
|
+
pg_size_pretty(pg_total_relation_size(schemaname||'.'||tablename) - pg_relation_size(schemaname||'.'||tablename)) AS external_size
|
|
797
|
+
FROM pg_tables
|
|
798
|
+
ORDER BY pg_total_relation_size(schemaname||'.'||tablename) DESC
|
|
799
|
+
LIMIT 20;
|
|
800
|
+
```
|
|
801
|
+
|
|
802
|
+
### Application-Level Monitoring
|
|
803
|
+
|
|
804
|
+
```javascript
|
|
805
|
+
// Monitor query performance
|
|
806
|
+
const queryDuration = new Map();
|
|
807
|
+
|
|
808
|
+
async function monitoredQuery(query, params) {
|
|
809
|
+
const start = Date.now();
|
|
810
|
+
|
|
811
|
+
try {
|
|
812
|
+
const result = await db.query(query, params);
|
|
813
|
+
const duration = Date.now() - start;
|
|
814
|
+
|
|
815
|
+
// Log slow queries
|
|
816
|
+
if (duration > 1000) {
|
|
817
|
+
console.warn(`Slow query (${duration}ms):`, query);
|
|
818
|
+
}
|
|
819
|
+
|
|
820
|
+
// Track query statistics
|
|
821
|
+
if (!queryDuration.has(query)) {
|
|
822
|
+
queryDuration.set(query, []);
|
|
823
|
+
}
|
|
824
|
+
queryDuration.get(query).push(duration);
|
|
825
|
+
|
|
826
|
+
return result;
|
|
827
|
+
} catch (error) {
|
|
828
|
+
console.error('Query error:', error);
|
|
829
|
+
throw error;
|
|
830
|
+
}
|
|
831
|
+
}
|
|
832
|
+
|
|
833
|
+
// Report query statistics
|
|
834
|
+
function reportQueryStats() {
|
|
835
|
+
for (const [query, durations] of queryDuration.entries()) {
|
|
836
|
+
const avg = durations.reduce((a, b) => a + b, 0) / durations.length;
|
|
837
|
+
const max = Math.max(...durations);
|
|
838
|
+
const min = Math.min(...durations);
|
|
839
|
+
|
|
840
|
+
console.log(`Query: ${query.substring(0, 50)}...`);
|
|
841
|
+
console.log(` Calls: ${durations.length}`);
|
|
842
|
+
console.log(` Avg: ${avg.toFixed(2)}ms`);
|
|
843
|
+
console.log(` Min: ${min}ms`);
|
|
844
|
+
console.log(` Max: ${max}ms`);
|
|
845
|
+
}
|
|
846
|
+
}
|
|
847
|
+
```
|
|
848
|
+
|
|
849
|
+
---
|
|
850
|
+
|
|
851
|
+
## Database-Specific Optimizations
|
|
852
|
+
|
|
853
|
+
### PostgreSQL
|
|
854
|
+
|
|
855
|
+
```sql
|
|
856
|
+
-- Vacuum and analyze regularly
|
|
857
|
+
VACUUM ANALYZE users;
|
|
858
|
+
|
|
859
|
+
-- Auto-vacuum settings (postgresql.conf)
|
|
860
|
+
-- autovacuum = on
|
|
861
|
+
-- autovacuum_vacuum_scale_factor = 0.1
|
|
862
|
+
-- autovacuum_analyze_scale_factor = 0.05
|
|
863
|
+
|
|
864
|
+
-- Increase work_mem for complex queries
|
|
865
|
+
SET work_mem = '256MB';
|
|
866
|
+
|
|
867
|
+
-- Increase maintenance_work_mem for index creation
|
|
868
|
+
SET maintenance_work_mem = '512MB';
|
|
869
|
+
|
|
870
|
+
-- Enable parallel query execution
|
|
871
|
+
SET max_parallel_workers_per_gather = 4;
|
|
872
|
+
|
|
873
|
+
-- Use EXPLAIN (ANALYZE, BUFFERS) for detailed query analysis
|
|
874
|
+
EXPLAIN (ANALYZE, BUFFERS)
|
|
875
|
+
SELECT * FROM orders WHERE user_id = 123;
|
|
876
|
+
```
|
|
877
|
+
|
|
878
|
+
### MySQL
|
|
879
|
+
|
|
880
|
+
```sql
|
|
881
|
+
-- Optimize table
|
|
882
|
+
OPTIMIZE TABLE users;
|
|
883
|
+
|
|
884
|
+
-- Analyze table
|
|
885
|
+
ANALYZE TABLE users;
|
|
886
|
+
|
|
887
|
+
-- Use query cache (MySQL 5.7 and earlier)
|
|
888
|
+
SET GLOBAL query_cache_size = 268435456; -- 256MB
|
|
889
|
+
SET GLOBAL query_cache_type = 1;
|
|
890
|
+
|
|
891
|
+
-- Increase buffer pool size (my.cnf)
|
|
892
|
+
-- innodb_buffer_pool_size = 1G
|
|
893
|
+
|
|
894
|
+
-- Enable slow query log (my.cnf)
|
|
895
|
+
-- slow_query_log = 1
|
|
896
|
+
-- long_query_time = 1
|
|
897
|
+
-- slow_query_log_file = /var/log/mysql/slow.log
|
|
898
|
+
```
|
|
899
|
+
|
|
900
|
+
### MongoDB
|
|
901
|
+
|
|
902
|
+
```javascript
|
|
903
|
+
// Create index
|
|
904
|
+
db.users.createIndex({ email: 1 });
|
|
905
|
+
|
|
906
|
+
// Create compound index
|
|
907
|
+
db.orders.createIndex({ user_id: 1, created_at: -1 });
|
|
908
|
+
|
|
909
|
+
// Analyze query performance
|
|
910
|
+
db.orders.find({ user_id: 123 }).explain('executionStats');
|
|
911
|
+
|
|
912
|
+
// Use aggregation pipeline for complex queries
|
|
913
|
+
db.orders.aggregate([
|
|
914
|
+
{ $match: { user_id: 123 } },
|
|
915
|
+
{ $group: { _id: '$status', count: { $sum: 1 } } },
|
|
916
|
+
{ $sort: { count: -1 } }
|
|
917
|
+
]);
|
|
918
|
+
|
|
919
|
+
// Use projection to limit returned fields
|
|
920
|
+
db.users.find({ email: 'user@example.com' }, { name: 1, email: 1 });
|
|
921
|
+
```
|
|
922
|
+
|
|
923
|
+
---
|
|
924
|
+
|
|
925
|
+
## Performance Optimization Checklist
|
|
926
|
+
|
|
927
|
+
### Schema Design
|
|
928
|
+
|
|
929
|
+
- [ ] Use appropriate data types (smallest that fits)
|
|
930
|
+
- [ ] Create indexes on foreign keys
|
|
931
|
+
- [ ] Create indexes on frequently queried columns
|
|
932
|
+
- [ ] Use composite indexes for multi-column queries
|
|
933
|
+
- [ ] Consider partial indexes for filtered queries
|
|
934
|
+
- [ ] Use covering indexes for index-only scans
|
|
935
|
+
- [ ] Normalize data to reduce redundancy
|
|
936
|
+
- [ ] Denormalize when read performance is critical
|
|
937
|
+
|
|
938
|
+
### Query Optimization
|
|
939
|
+
|
|
940
|
+
- [ ] Select only needed columns (avoid SELECT *)
|
|
941
|
+
- [ ] Use LIMIT for pagination
|
|
942
|
+
- [ ] Avoid N+1 queries (use JOINs or batch queries)
|
|
943
|
+
- [ ] Use EXPLAIN ANALYZE to understand query plans
|
|
944
|
+
- [ ] Optimize WHERE clauses (avoid functions on indexed columns)
|
|
945
|
+
- [ ] Use appropriate JOIN types
|
|
946
|
+
- [ ] Avoid subqueries in SELECT (use JOINs instead)
|
|
947
|
+
- [ ] Use EXISTS instead of COUNT(*) for existence checks
|
|
948
|
+
|
|
949
|
+
### Connection Management
|
|
950
|
+
|
|
951
|
+
- [ ] Use connection pooling
|
|
952
|
+
- [ ] Set appropriate pool size (10-20 connections)
|
|
953
|
+
- [ ] Monitor pool utilization
|
|
954
|
+
- [ ] Implement connection timeouts
|
|
955
|
+
- [ ] Release connections after use
|
|
956
|
+
|
|
957
|
+
### Caching
|
|
958
|
+
|
|
959
|
+
- [ ] Cache frequently accessed data
|
|
960
|
+
- [ ] Set appropriate TTL
|
|
961
|
+
- [ ] Invalidate cache on updates
|
|
962
|
+
- [ ] Monitor cache hit ratio (target > 90%)
|
|
963
|
+
- [ ] Use Redis or Memcached for distributed caching
|
|
964
|
+
|
|
965
|
+
### Batch Operations
|
|
966
|
+
|
|
967
|
+
- [ ] Use batch inserts for multiple rows
|
|
968
|
+
- [ ] Use batch updates with IN or ANY
|
|
969
|
+
- [ ] Use COPY for bulk data loading
|
|
970
|
+
- [ ] Limit batch size (1000-5000 rows)
|
|
971
|
+
|
|
972
|
+
### Monitoring
|
|
973
|
+
|
|
974
|
+
- [ ] Monitor slow queries (> 1 second)
|
|
975
|
+
- [ ] Track query execution time trends
|
|
976
|
+
- [ ] Monitor connection pool utilization
|
|
977
|
+
- [ ] Monitor cache hit ratio
|
|
978
|
+
- [ ] Monitor database size and growth
|
|
979
|
+
- [ ] Set up alerts for performance degradation
|
|
980
|
+
|
|
981
|
+
---
|
|
982
|
+
|
|
983
|
+
## Common Performance Pitfalls
|
|
984
|
+
|
|
985
|
+
### ❌ DON'T
|
|
986
|
+
|
|
987
|
+
```sql
|
|
988
|
+
-- Don't use SELECT *
|
|
989
|
+
SELECT * FROM users;
|
|
990
|
+
|
|
991
|
+
-- Don't use functions on indexed columns
|
|
992
|
+
SELECT * FROM users WHERE LOWER(email) = 'user@example.com';
|
|
993
|
+
|
|
994
|
+
-- Don't use leading wildcards
|
|
995
|
+
SELECT * FROM users WHERE email LIKE '%@example.com';
|
|
996
|
+
|
|
997
|
+
-- Don't use OR on different columns (prevents index usage)
|
|
998
|
+
SELECT * FROM users WHERE email = 'user@example.com' OR name = 'John';
|
|
999
|
+
|
|
1000
|
+
-- Don't use subqueries in SELECT (N+1 problem)
|
|
1001
|
+
SELECT
|
|
1002
|
+
u.id,
|
|
1003
|
+
(SELECT COUNT(*) FROM orders WHERE user_id = u.id) AS order_count
|
|
1004
|
+
FROM users u;
|
|
1005
|
+
|
|
1006
|
+
-- Don't forget LIMIT on large result sets
|
|
1007
|
+
SELECT * FROM orders ORDER BY created_at DESC;
|
|
1008
|
+
|
|
1009
|
+
-- Don't use OFFSET for large offsets
|
|
1010
|
+
SELECT * FROM orders ORDER BY created_at DESC LIMIT 20 OFFSET 10000;
|
|
1011
|
+
```
|
|
1012
|
+
|
|
1013
|
+
### ✅ DO
|
|
1014
|
+
|
|
1015
|
+
```sql
|
|
1016
|
+
-- Select only needed columns
|
|
1017
|
+
SELECT id, email, name FROM users;
|
|
1018
|
+
|
|
1019
|
+
-- Use functional index or case-insensitive collation
|
|
1020
|
+
CREATE INDEX idx_users_email_lower ON users(LOWER(email));
|
|
1021
|
+
SELECT * FROM users WHERE LOWER(email) = 'user@example.com';
|
|
1022
|
+
|
|
1023
|
+
-- Avoid leading wildcards
|
|
1024
|
+
SELECT * FROM users WHERE email LIKE 'user@%';
|
|
1025
|
+
|
|
1026
|
+
-- Use UNION or separate queries
|
|
1027
|
+
SELECT * FROM users WHERE email = 'user@example.com'
|
|
1028
|
+
UNION
|
|
1029
|
+
SELECT * FROM users WHERE name = 'John';
|
|
1030
|
+
|
|
1031
|
+
-- Use JOIN with aggregation
|
|
1032
|
+
SELECT
|
|
1033
|
+
u.id,
|
|
1034
|
+
COUNT(o.id) AS order_count
|
|
1035
|
+
FROM users u
|
|
1036
|
+
LEFT JOIN orders o ON o.user_id = u.id
|
|
1037
|
+
GROUP BY u.id;
|
|
1038
|
+
|
|
1039
|
+
-- Always use LIMIT
|
|
1040
|
+
SELECT * FROM orders ORDER BY created_at DESC LIMIT 20;
|
|
1041
|
+
|
|
1042
|
+
-- Use cursor-based pagination
|
|
1043
|
+
SELECT * FROM orders
|
|
1044
|
+
WHERE (created_at, id) < ('2024-01-15 10:30:00', 12345)
|
|
1045
|
+
ORDER BY created_at DESC, id DESC
|
|
1046
|
+
LIMIT 20;
|
|
1047
|
+
```
|
|
1048
|
+
|
|
1049
|
+
---
|
|
1050
|
+
|
|
1051
|
+
## Summary
|
|
1052
|
+
|
|
1053
|
+
**Key Performance Principles:**
|
|
1054
|
+
|
|
1055
|
+
1. **Index Strategically**: Create indexes on frequently queried columns, but avoid over-indexing
|
|
1056
|
+
2. **Optimize Queries**: Use EXPLAIN ANALYZE, select only needed columns, avoid N+1 queries
|
|
1057
|
+
3. **Use Connection Pooling**: Reuse connections, set appropriate pool size
|
|
1058
|
+
4. **Cache Wisely**: Cache frequently accessed data with appropriate TTL
|
|
1059
|
+
5. **Batch Operations**: Use batch inserts/updates/deletes for multiple rows
|
|
1060
|
+
6. **Monitor Continuously**: Track slow queries, connection pool, cache hit ratio
|
|
1061
|
+
|
|
1062
|
+
**Performance Optimization Workflow:**
|
|
1063
|
+
1. **Identify**: Use monitoring to find slow queries
|
|
1064
|
+
2. **Analyze**: Use EXPLAIN ANALYZE to understand query execution
|
|
1065
|
+
3. **Optimize**: Add indexes, rewrite queries, implement caching
|
|
1066
|
+
4. **Test**: Measure performance improvement
|
|
1067
|
+
5. **Monitor**: Track metrics to ensure sustained performance
|
|
1068
|
+
|
|
1069
|
+
**Critical Rules:**
|
|
1070
|
+
- ❌ NEVER use SELECT * in production
|
|
1071
|
+
- ❌ NEVER forget to add indexes on foreign keys
|
|
1072
|
+
- ❌ NEVER use OFFSET for large offsets
|
|
1073
|
+
- ❌ NEVER ignore slow query warnings
|
|
1074
|
+
- ❌ NEVER skip connection pooling
|
|
1075
|
+
|
|
1076
|
+
|