aigroup-workflow 2.2.0 → 2.2.2
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/.claude/commands/fix-build.md +10 -5
- package/.claude/commands/init-project.md +13 -8
- package/.claude/commands/plan.md +15 -8
- package/.claude/commands/review.md +12 -6
- package/.claude/commands/tdd.md +11 -5
- package/.claude/commands/workflow-start.md +20 -11
- package/.claude/settings.json +28 -0
- package/.codex/agents/architect.toml +207 -0
- package/.codex/agents/build-error-resolver.toml +110 -0
- package/.codex/agents/code-reviewer.toml +233 -0
- package/.codex/agents/doc-updater.toml +103 -0
- package/.codex/agents/e2e-runner.toml +103 -0
- package/.codex/agents/get-current-datetime.toml +23 -0
- package/.codex/agents/init-architect.toml +181 -0
- package/.codex/agents/planner.toml +208 -0
- package/.codex/agents/refactor-cleaner.toml +81 -0
- package/.codex/agents/rust-reviewer.toml +90 -0
- package/.codex/agents/security-reviewer.toml +104 -0
- package/.codex/agents/tdd-guide.toml +87 -0
- package/AGENTS.md +2 -2
- package/CLAUDE.md +23 -1
- package/LICENSE +20 -20
- package/README.md +333 -333
- package/agents/a11y-architect.md +141 -141
- package/agents/architect.md +211 -211
- package/agents/build-error-resolver.md +114 -114
- package/agents/chief-of-staff.md +151 -151
- package/agents/code-architect.md +71 -71
- package/agents/code-explorer.md +69 -69
- package/agents/code-reviewer.md +237 -237
- package/agents/code-simplifier.md +47 -47
- package/agents/comment-analyzer.md +45 -45
- package/agents/conversation-analyzer.md +52 -52
- package/agents/cpp-build-resolver.md +90 -90
- package/agents/cpp-reviewer.md +72 -72
- package/agents/csharp-reviewer.md +101 -101
- package/agents/dart-build-resolver.md +201 -201
- package/agents/database-reviewer.md +91 -91
- package/agents/doc-updater.md +107 -107
- package/agents/docs-lookup.md +68 -68
- package/agents/e2e-runner.md +107 -107
- package/agents/flutter-reviewer.md +243 -243
- package/agents/gan-evaluator.md +209 -209
- package/agents/gan-generator.md +131 -131
- package/agents/gan-planner.md +99 -99
- package/agents/get-current-datetime.md +26 -26
- package/agents/go-build-resolver.md +94 -94
- package/agents/go-reviewer.md +76 -76
- package/agents/harness-optimizer.md +35 -35
- package/agents/healthcare-reviewer.md +83 -83
- package/agents/java-build-resolver.md +153 -153
- package/agents/java-reviewer.md +92 -92
- package/agents/kotlin-build-resolver.md +118 -118
- package/agents/kotlin-reviewer.md +159 -159
- package/agents/loop-operator.md +36 -36
- package/agents/opensource-forker.md +198 -198
- package/agents/opensource-packager.md +249 -249
- package/agents/opensource-sanitizer.md +188 -188
- package/agents/performance-optimizer.md +446 -446
- package/agents/planner.md +212 -212
- package/agents/pr-test-analyzer.md +45 -45
- package/agents/python-reviewer.md +98 -98
- package/agents/pytorch-build-resolver.md +120 -120
- package/agents/refactor-cleaner.md +85 -85
- package/agents/rust-build-resolver.md +148 -148
- package/agents/rust-reviewer.md +94 -94
- package/agents/security-reviewer.md +108 -108
- package/agents/seo-specialist.md +59 -59
- package/agents/silent-failure-hunter.md +50 -50
- package/agents/tdd-guide.md +91 -91
- package/agents/type-design-analyzer.md +41 -41
- package/agents/typescript-reviewer.md +112 -112
- package/cli/commands/update.mjs +1 -1
- package/cli/utils/scaffold.mjs +53 -0
- package/docs/rules/agents.md +166 -50
- package/docs/rules/cpp/coding-style.md +44 -44
- package/docs/rules/cpp/hooks.md +39 -39
- package/docs/rules/cpp/patterns.md +51 -51
- package/docs/rules/cpp/security.md +51 -51
- package/docs/rules/cpp/testing.md +44 -44
- package/docs/rules/csharp/coding-style.md +72 -72
- package/docs/rules/csharp/hooks.md +25 -25
- package/docs/rules/csharp/patterns.md +50 -50
- package/docs/rules/csharp/security.md +58 -58
- package/docs/rules/csharp/testing.md +46 -46
- package/docs/rules/dart/coding-style.md +159 -159
- package/docs/rules/dart/hooks.md +66 -66
- package/docs/rules/dart/patterns.md +261 -261
- package/docs/rules/dart/security.md +135 -135
- package/docs/rules/dart/testing.md +215 -215
- package/docs/rules/golang/coding-style.md +32 -32
- package/docs/rules/golang/hooks.md +17 -17
- package/docs/rules/golang/patterns.md +45 -45
- package/docs/rules/golang/security.md +34 -34
- package/docs/rules/golang/testing.md +31 -31
- package/docs/rules/java/coding-style.md +114 -114
- package/docs/rules/java/hooks.md +18 -18
- package/docs/rules/java/patterns.md +146 -146
- package/docs/rules/java/security.md +100 -100
- package/docs/rules/java/testing.md +131 -131
- package/docs/rules/kotlin/coding-style.md +86 -86
- package/docs/rules/kotlin/hooks.md +17 -17
- package/docs/rules/kotlin/patterns.md +146 -146
- package/docs/rules/kotlin/security.md +82 -82
- package/docs/rules/kotlin/testing.md +128 -128
- package/docs/rules/perl/coding-style.md +46 -46
- package/docs/rules/perl/hooks.md +22 -22
- package/docs/rules/perl/patterns.md +76 -76
- package/docs/rules/perl/security.md +69 -69
- package/docs/rules/perl/testing.md +54 -54
- package/docs/rules/php/coding-style.md +40 -40
- package/docs/rules/php/hooks.md +24 -24
- package/docs/rules/php/patterns.md +33 -33
- package/docs/rules/php/security.md +37 -37
- package/docs/rules/php/testing.md +39 -39
- package/docs/rules/python/coding-style.md +42 -42
- package/docs/rules/python/hooks.md +19 -19
- package/docs/rules/python/patterns.md +39 -39
- package/docs/rules/python/security.md +30 -30
- package/docs/rules/python/testing.md +38 -38
- package/docs/rules/rust/coding-style.md +151 -151
- package/docs/rules/rust/hooks.md +16 -16
- package/docs/rules/rust/patterns.md +168 -168
- package/docs/rules/rust/security.md +141 -141
- package/docs/rules/rust/testing.md +154 -154
- package/docs/rules/swift/coding-style.md +47 -47
- package/docs/rules/swift/hooks.md +20 -20
- package/docs/rules/swift/patterns.md +66 -66
- package/docs/rules/swift/security.md +33 -33
- package/docs/rules/swift/testing.md +45 -45
- package/docs/rules/typescript/coding-style.md +199 -199
- package/docs/rules/typescript/hooks.md +22 -22
- package/docs/rules/typescript/patterns.md +52 -52
- package/docs/rules/typescript/security.md +28 -28
- package/docs/rules/typescript/testing.md +18 -18
- package/docs/rules/web/coding-style.md +96 -96
- package/docs/rules/web/design-quality.md +62 -62
- package/docs/rules/web/hooks.md +120 -120
- package/docs/rules/web/patterns.md +79 -79
- package/docs/rules/web/performance.md +64 -64
- package/docs/rules/web/security.md +57 -57
- package/docs/rules/web/testing.md +55 -55
- package/docs/templates/README.md +36 -36
- package/docs/templates/ai-project-final.md +124 -124
- package/docs/templates/ai-project.md +105 -105
- package/docs/templates/api.md +157 -157
- package/docs/templates/bug.md +62 -62
- package/docs/templates/code-review.md +87 -87
- package/docs/templates/generic.md +116 -116
- package/docs/templates/implementation-plan.md +1 -1
- package/docs/templates/meeting.md +68 -68
- package/docs/templates/prd.md +98 -98
- package/docs/templates/ui.md +134 -134
- package/docs/workflow-pipeline.md +11 -10
- package/package.json +40 -39
- package/scripts/hooks/checks/orchestration-artifacts.cjs +28 -23
- package/scripts/hooks/checks/workflow-state.cjs +4 -5
- package/scripts/orchestration/lib/orchestrator.cjs +344 -117
- package/scripts/orchestration/lib/validate.cjs +145 -0
- package/scripts/orchestration/session.cjs +88 -44
- package/skills/SUPERPOWERS-LICENSE +21 -21
- package/skills/ai-ml/fine-tuning-expert/SKILL.md +162 -162
- package/skills/ai-ml/fine-tuning-expert/references/dataset-preparation.md +540 -540
- package/skills/ai-ml/fine-tuning-expert/references/deployment-optimization.md +673 -673
- package/skills/ai-ml/fine-tuning-expert/references/evaluation-metrics.md +597 -597
- package/skills/ai-ml/fine-tuning-expert/references/hyperparameter-tuning.md +565 -565
- package/skills/ai-ml/fine-tuning-expert/references/lora-peft.md +347 -347
- package/skills/ai-ml/ml-pipeline/SKILL.md +159 -159
- package/skills/ai-ml/ml-pipeline/references/experiment-tracking.md +833 -833
- package/skills/ai-ml/ml-pipeline/references/feature-engineering.md +631 -631
- package/skills/ai-ml/ml-pipeline/references/model-validation.md +978 -978
- package/skills/ai-ml/ml-pipeline/references/pipeline-orchestration.md +907 -907
- package/skills/ai-ml/ml-pipeline/references/training-pipelines.md +782 -782
- package/skills/ai-ml/rag-architect/SKILL.md +194 -194
- package/skills/ai-ml/rag-architect/references/chunking-strategies.md +878 -878
- package/skills/ai-ml/rag-architect/references/embedding-models.md +561 -561
- package/skills/ai-ml/rag-architect/references/rag-evaluation.md +833 -833
- package/skills/ai-ml/rag-architect/references/retrieval-optimization.md +795 -795
- package/skills/ai-ml/rag-architect/references/vector-databases.md +589 -589
- package/skills/ai-ml/spark-engineer/SKILL.md +148 -148
- package/skills/ai-ml/spark-engineer/references/partitioning-caching.md +543 -543
- package/skills/ai-ml/spark-engineer/references/performance-tuning.md +544 -544
- package/skills/ai-ml/spark-engineer/references/rdd-operations.md +599 -599
- package/skills/ai-ml/spark-engineer/references/spark-sql-dataframes.md +474 -474
- package/skills/ai-ml/spark-engineer/references/streaming-patterns.md +786 -786
- package/skills/backend/api-designer/SKILL.md +217 -217
- package/skills/backend/api-designer/references/error-handling.md +541 -541
- package/skills/backend/api-designer/references/openapi.md +824 -824
- package/skills/backend/api-designer/references/pagination.md +494 -494
- package/skills/backend/api-designer/references/rest-patterns.md +335 -335
- package/skills/backend/api-designer/references/versioning.md +391 -391
- package/skills/backend/architecture-designer/SKILL.md +117 -117
- package/skills/backend/architecture-designer/references/adr-template.md +116 -116
- package/skills/backend/architecture-designer/references/architecture-patterns.md +111 -111
- package/skills/backend/architecture-designer/references/database-selection.md +102 -102
- package/skills/backend/architecture-designer/references/nfr-checklist.md +112 -112
- package/skills/backend/architecture-designer/references/system-design.md +100 -100
- package/skills/backend/code-documenter/SKILL.md +147 -147
- package/skills/backend/code-documenter/references/api-docs-fastapi-django.md +166 -166
- package/skills/backend/code-documenter/references/api-docs-nestjs-express.md +220 -220
- package/skills/backend/code-documenter/references/coverage-reports.md +125 -125
- package/skills/backend/code-documenter/references/documentation-systems.md +333 -333
- package/skills/backend/code-documenter/references/interactive-api-docs.md +531 -531
- package/skills/backend/code-documenter/references/python-docstrings.md +121 -121
- package/skills/backend/code-documenter/references/typescript-jsdoc.md +145 -145
- package/skills/backend/code-documenter/references/user-guides-tutorials.md +530 -530
- package/skills/backend/debugging-wizard/SKILL.md +105 -105
- package/skills/backend/debugging-wizard/references/common-patterns.md +132 -132
- package/skills/backend/debugging-wizard/references/debugging-tools.md +140 -140
- package/skills/backend/debugging-wizard/references/quick-fixes.md +177 -177
- package/skills/backend/debugging-wizard/references/strategies.md +142 -142
- package/skills/backend/debugging-wizard/references/systematic-debugging.md +367 -367
- package/skills/backend/feature-forge/SKILL.md +98 -98
- package/skills/backend/feature-forge/references/acceptance-criteria.md +104 -104
- package/skills/backend/feature-forge/references/ears-syntax.md +99 -99
- package/skills/backend/feature-forge/references/interview-questions.md +150 -150
- package/skills/backend/feature-forge/references/pre-discovery-subagents.md +54 -54
- package/skills/backend/feature-forge/references/specification-template.md +103 -103
- package/skills/backend/fullstack-guardian/SKILL.md +105 -105
- package/skills/backend/fullstack-guardian/references/api-design-standards.md +307 -307
- package/skills/backend/fullstack-guardian/references/architecture-decisions.md +350 -350
- package/skills/backend/fullstack-guardian/references/backend-patterns.md +237 -237
- package/skills/backend/fullstack-guardian/references/common-patterns.md +134 -134
- package/skills/backend/fullstack-guardian/references/deliverables-checklist.md +354 -354
- package/skills/backend/fullstack-guardian/references/design-template.md +91 -91
- package/skills/backend/fullstack-guardian/references/error-handling.md +135 -135
- package/skills/backend/fullstack-guardian/references/frontend-patterns.md +340 -340
- package/skills/backend/fullstack-guardian/references/integration-patterns.md +333 -333
- package/skills/backend/fullstack-guardian/references/security-checklist.md +106 -106
- package/skills/backend/graphql-architect/SKILL.md +146 -146
- package/skills/backend/graphql-architect/references/federation.md +418 -418
- package/skills/backend/graphql-architect/references/migration-from-rest.md +1141 -1141
- package/skills/backend/graphql-architect/references/resolvers.md +425 -425
- package/skills/backend/graphql-architect/references/schema-design.md +393 -393
- package/skills/backend/graphql-architect/references/security.md +569 -569
- package/skills/backend/graphql-architect/references/subscriptions.md +510 -510
- package/skills/backend/legacy-modernizer/SKILL.md +137 -137
- package/skills/backend/legacy-modernizer/references/legacy-testing.md +381 -381
- package/skills/backend/legacy-modernizer/references/migration-strategies.md +423 -423
- package/skills/backend/legacy-modernizer/references/refactoring-patterns.md +395 -395
- package/skills/backend/legacy-modernizer/references/strangler-fig-pattern.md +281 -281
- package/skills/backend/legacy-modernizer/references/system-assessment.md +487 -487
- package/skills/backend/microservices-architect/SKILL.md +164 -164
- package/skills/backend/microservices-architect/references/communication.md +499 -499
- package/skills/backend/microservices-architect/references/data.md +721 -721
- package/skills/backend/microservices-architect/references/decomposition.md +344 -344
- package/skills/backend/microservices-architect/references/observability.md +805 -805
- package/skills/backend/microservices-architect/references/patterns.md +603 -603
- package/skills/database/database-optimizer/SKILL.md +147 -147
- package/skills/database/database-optimizer/references/index-strategies.md +331 -331
- package/skills/database/database-optimizer/references/monitoring-analysis.md +501 -501
- package/skills/database/database-optimizer/references/mysql-tuning.md +452 -452
- package/skills/database/database-optimizer/references/postgresql-tuning.md +413 -413
- package/skills/database/database-optimizer/references/query-optimization.md +251 -251
- package/skills/database/postgres-pro/SKILL.md +152 -152
- package/skills/database/postgres-pro/references/extensions.md +404 -404
- package/skills/database/postgres-pro/references/jsonb.md +321 -321
- package/skills/database/postgres-pro/references/maintenance.md +481 -481
- package/skills/database/postgres-pro/references/performance.md +265 -265
- package/skills/database/postgres-pro/references/replication.md +446 -446
- package/skills/database/sql-pro/SKILL.md +129 -129
- package/skills/database/sql-pro/references/database-design.md +402 -402
- package/skills/database/sql-pro/references/dialect-differences.md +419 -419
- package/skills/database/sql-pro/references/optimization.md +384 -384
- package/skills/database/sql-pro/references/query-patterns.md +285 -285
- package/skills/database/sql-pro/references/window-functions.md +328 -328
- package/skills/dotnet/csharp-developer/SKILL.md +125 -125
- package/skills/dotnet/csharp-developer/references/aspnet-core.md +394 -394
- package/skills/dotnet/csharp-developer/references/blazor.md +553 -553
- package/skills/dotnet/csharp-developer/references/entity-framework.md +409 -409
- package/skills/dotnet/csharp-developer/references/modern-csharp.md +248 -248
- package/skills/dotnet/csharp-developer/references/performance.md +498 -498
- package/skills/dotnet/dotnet-core-expert/SKILL.md +138 -138
- package/skills/dotnet/dotnet-core-expert/references/authentication.md +546 -546
- package/skills/dotnet/dotnet-core-expert/references/clean-architecture.md +455 -455
- package/skills/dotnet/dotnet-core-expert/references/cloud-native.md +548 -548
- package/skills/dotnet/dotnet-core-expert/references/entity-framework.md +440 -440
- package/skills/dotnet/dotnet-core-expert/references/minimal-apis.md +319 -319
- package/skills/frontend/angular-architect/SKILL.md +152 -152
- package/skills/frontend/angular-architect/references/components.md +297 -297
- package/skills/frontend/angular-architect/references/ngrx.md +401 -401
- package/skills/frontend/angular-architect/references/routing.md +361 -361
- package/skills/frontend/angular-architect/references/rxjs.md +319 -319
- package/skills/frontend/angular-architect/references/testing.md +405 -405
- package/skills/frontend/design-commands/design.md +91 -91
- package/skills/frontend/design-commands/handoff.md +97 -97
- package/skills/frontend/design-commands/prototype.md +120 -120
- package/skills/frontend/design-commands/spec.md +160 -160
- package/skills/frontend/design-commands/style.md +78 -78
- package/skills/frontend/flutter-expert/SKILL.md +138 -138
- package/skills/frontend/flutter-expert/references/bloc-state.md +259 -259
- package/skills/frontend/flutter-expert/references/gorouter-navigation.md +119 -119
- package/skills/frontend/flutter-expert/references/performance.md +99 -99
- package/skills/frontend/flutter-expert/references/project-structure.md +118 -118
- package/skills/frontend/flutter-expert/references/riverpod-state.md +130 -130
- package/skills/frontend/flutter-expert/references/widget-patterns.md +123 -123
- package/skills/frontend/nextjs-developer/SKILL.md +143 -143
- package/skills/frontend/nextjs-developer/references/app-router.md +311 -311
- package/skills/frontend/nextjs-developer/references/data-fetching.md +482 -482
- package/skills/frontend/nextjs-developer/references/deployment.md +545 -545
- package/skills/frontend/nextjs-developer/references/server-actions.md +462 -462
- package/skills/frontend/nextjs-developer/references/server-components.md +384 -384
- package/skills/frontend/react-expert/SKILL.md +149 -149
- package/skills/frontend/react-expert/references/hooks-patterns.md +162 -162
- package/skills/frontend/react-expert/references/migration-class-to-modern.md +1119 -1119
- package/skills/frontend/react-expert/references/performance.md +168 -168
- package/skills/frontend/react-expert/references/react-19-features.md +174 -174
- package/skills/frontend/react-expert/references/server-components.md +143 -143
- package/skills/frontend/react-expert/references/state-management.md +171 -171
- package/skills/frontend/react-expert/references/testing-react.md +174 -174
- package/skills/frontend/react-native-expert/SKILL.md +185 -185
- package/skills/frontend/react-native-expert/references/expo-router.md +187 -187
- package/skills/frontend/react-native-expert/references/list-optimization.md +204 -204
- package/skills/frontend/react-native-expert/references/platform-handling.md +188 -188
- package/skills/frontend/react-native-expert/references/project-structure.md +171 -171
- package/skills/frontend/react-native-expert/references/storage-hooks.md +173 -173
- package/skills/frontend/senior-frontend/SKILL.md +477 -477
- package/skills/frontend/senior-frontend/references/frontend_best_practices.md +806 -806
- package/skills/frontend/senior-frontend/references/nextjs_optimization_guide.md +724 -724
- package/skills/frontend/senior-frontend/references/react_patterns.md +746 -746
- package/skills/frontend/senior-frontend/scripts/bundle_analyzer.py +407 -407
- package/skills/frontend/senior-frontend/scripts/component_generator.py +329 -329
- package/skills/frontend/senior-frontend/scripts/frontend_scaffolder.py +1005 -1005
- package/skills/frontend/ui-ux-pro-max/SKILL.md +386 -386
- package/skills/frontend/ui-ux-pro-max/data/charts.csv +26 -26
- package/skills/frontend/ui-ux-pro-max/data/colors.csv +97 -97
- package/skills/frontend/ui-ux-pro-max/data/icons.csv +101 -101
- package/skills/frontend/ui-ux-pro-max/data/landing.csv +31 -31
- package/skills/frontend/ui-ux-pro-max/data/products.csv +96 -96
- package/skills/frontend/ui-ux-pro-max/data/react-performance.csv +45 -45
- package/skills/frontend/ui-ux-pro-max/data/stacks/astro.csv +54 -54
- package/skills/frontend/ui-ux-pro-max/data/stacks/flutter.csv +53 -53
- package/skills/frontend/ui-ux-pro-max/data/stacks/html-tailwind.csv +56 -56
- package/skills/frontend/ui-ux-pro-max/data/stacks/jetpack-compose.csv +53 -53
- package/skills/frontend/ui-ux-pro-max/data/stacks/nextjs.csv +53 -53
- package/skills/frontend/ui-ux-pro-max/data/stacks/nuxt-ui.csv +51 -51
- package/skills/frontend/ui-ux-pro-max/data/stacks/nuxtjs.csv +59 -59
- package/skills/frontend/ui-ux-pro-max/data/stacks/react-native.csv +52 -52
- package/skills/frontend/ui-ux-pro-max/data/stacks/react.csv +54 -54
- package/skills/frontend/ui-ux-pro-max/data/stacks/shadcn.csv +61 -61
- package/skills/frontend/ui-ux-pro-max/data/stacks/svelte.csv +54 -54
- package/skills/frontend/ui-ux-pro-max/data/stacks/swiftui.csv +51 -51
- package/skills/frontend/ui-ux-pro-max/data/stacks/vue.csv +50 -50
- package/skills/frontend/ui-ux-pro-max/data/styles.csv +68 -68
- package/skills/frontend/ui-ux-pro-max/data/typography.csv +57 -57
- package/skills/frontend/ui-ux-pro-max/data/ui-reasoning.csv +101 -101
- package/skills/frontend/ui-ux-pro-max/data/ux-guidelines.csv +99 -99
- package/skills/frontend/ui-ux-pro-max/data/web-interface.csv +31 -31
- package/skills/frontend/ui-ux-pro-max/scripts/core.py +253 -253
- package/skills/frontend/ui-ux-pro-max/scripts/design_system.py +1067 -1067
- package/skills/frontend/ui-ux-pro-max/scripts/search.py +114 -114
- package/skills/frontend/vue-expert/SKILL.md +98 -98
- package/skills/frontend/vue-expert/references/build-tooling.md +480 -480
- package/skills/frontend/vue-expert/references/components.md +448 -448
- package/skills/frontend/vue-expert/references/composition-api.md +299 -299
- package/skills/frontend/vue-expert/references/mobile-hybrid.md +636 -636
- package/skills/frontend/vue-expert/references/nuxt.md +669 -669
- package/skills/frontend/vue-expert/references/state-management.md +449 -449
- package/skills/frontend/vue-expert/references/typescript.md +584 -584
- package/skills/frontend/vue-expert-js/SKILL.md +167 -167
- package/skills/frontend/vue-expert-js/references/component-architecture.md +219 -219
- package/skills/frontend/vue-expert-js/references/composables-patterns.md +183 -183
- package/skills/frontend/vue-expert-js/references/jsdoc-typing.md +535 -535
- package/skills/frontend/vue-expert-js/references/state-management.md +249 -249
- package/skills/frontend/vue-expert-js/references/testing-patterns.md +237 -237
- package/skills/go-rust-cpp/cpp-pro/SKILL.md +115 -115
- package/skills/go-rust-cpp/cpp-pro/references/build-tooling.md +440 -440
- package/skills/go-rust-cpp/cpp-pro/references/concurrency.md +437 -437
- package/skills/go-rust-cpp/cpp-pro/references/memory-performance.md +397 -397
- package/skills/go-rust-cpp/cpp-pro/references/modern-cpp.md +304 -304
- package/skills/go-rust-cpp/cpp-pro/references/templates.md +357 -357
- package/skills/go-rust-cpp/golang-pro/SKILL.md +122 -122
- package/skills/go-rust-cpp/golang-pro/references/concurrency.md +329 -329
- package/skills/go-rust-cpp/golang-pro/references/generics.md +442 -442
- package/skills/go-rust-cpp/golang-pro/references/interfaces.md +432 -432
- package/skills/go-rust-cpp/golang-pro/references/project-structure.md +477 -477
- package/skills/go-rust-cpp/golang-pro/references/testing.md +451 -451
- package/skills/go-rust-cpp/rust-engineer/SKILL.md +167 -167
- package/skills/go-rust-cpp/rust-engineer/references/async.md +458 -458
- package/skills/go-rust-cpp/rust-engineer/references/error-handling.md +334 -334
- package/skills/go-rust-cpp/rust-engineer/references/ownership.md +278 -278
- package/skills/go-rust-cpp/rust-engineer/references/testing.md +470 -470
- package/skills/go-rust-cpp/rust-engineer/references/traits.md +413 -413
- package/skills/infra/cli-developer/SKILL.md +113 -113
- package/skills/infra/cli-developer/references/design-patterns.md +221 -221
- package/skills/infra/cli-developer/references/go-cli.md +540 -540
- package/skills/infra/cli-developer/references/node-cli.md +383 -383
- package/skills/infra/cli-developer/references/python-cli.md +422 -422
- package/skills/infra/cli-developer/references/ux-patterns.md +448 -448
- package/skills/infra/cloud-architect/SKILL.md +216 -216
- package/skills/infra/cloud-architect/references/aws.md +394 -394
- package/skills/infra/cloud-architect/references/azure.md +562 -562
- package/skills/infra/cloud-architect/references/cost.md +582 -582
- package/skills/infra/cloud-architect/references/gcp.md +633 -633
- package/skills/infra/cloud-architect/references/multi-cloud.md +483 -483
- package/skills/infra/devops-engineer/SKILL.md +144 -144
- package/skills/infra/devops-engineer/references/deployment-strategies.md +241 -241
- package/skills/infra/devops-engineer/references/docker-patterns.md +113 -113
- package/skills/infra/devops-engineer/references/github-actions.md +139 -139
- package/skills/infra/devops-engineer/references/incident-response.md +331 -331
- package/skills/infra/devops-engineer/references/kubernetes.md +154 -154
- package/skills/infra/devops-engineer/references/platform-engineering.md +417 -417
- package/skills/infra/devops-engineer/references/release-automation.md +527 -527
- package/skills/infra/devops-engineer/references/terraform-iac.md +141 -141
- package/skills/infra/kubernetes-specialist/SKILL.md +241 -241
- package/skills/infra/kubernetes-specialist/references/configuration.md +452 -452
- package/skills/infra/kubernetes-specialist/references/cost-optimization.md +458 -458
- package/skills/infra/kubernetes-specialist/references/custom-operators.md +563 -563
- package/skills/infra/kubernetes-specialist/references/gitops.md +530 -530
- package/skills/infra/kubernetes-specialist/references/helm-charts.md +912 -912
- package/skills/infra/kubernetes-specialist/references/multi-cluster.md +507 -507
- package/skills/infra/kubernetes-specialist/references/networking.md +447 -447
- package/skills/infra/kubernetes-specialist/references/service-mesh.md +459 -459
- package/skills/infra/kubernetes-specialist/references/storage.md +535 -535
- package/skills/infra/kubernetes-specialist/references/troubleshooting.md +414 -414
- package/skills/infra/kubernetes-specialist/references/workloads.md +377 -377
- package/skills/infra/mcp-developer/SKILL.md +143 -143
- package/skills/infra/mcp-developer/references/protocol.md +244 -244
- package/skills/infra/mcp-developer/references/python-sdk.md +367 -367
- package/skills/infra/mcp-developer/references/resources.md +554 -554
- package/skills/infra/mcp-developer/references/tools.md +480 -480
- package/skills/infra/mcp-developer/references/typescript-sdk.md +350 -350
- package/skills/infra/monitoring-expert/SKILL.md +176 -176
- package/skills/infra/monitoring-expert/references/alerting-rules.md +141 -141
- package/skills/infra/monitoring-expert/references/application-profiling.md +331 -331
- package/skills/infra/monitoring-expert/references/capacity-planning.md +344 -344
- package/skills/infra/monitoring-expert/references/dashboards.md +126 -126
- package/skills/infra/monitoring-expert/references/opentelemetry.md +123 -123
- package/skills/infra/monitoring-expert/references/performance-testing.md +269 -269
- package/skills/infra/monitoring-expert/references/prometheus-metrics.md +136 -136
- package/skills/infra/monitoring-expert/references/structured-logging.md +142 -142
- package/skills/infra/sre-engineer/SKILL.md +181 -181
- package/skills/infra/sre-engineer/references/automation-toil.md +492 -492
- package/skills/infra/sre-engineer/references/error-budget-policy.md +334 -334
- package/skills/infra/sre-engineer/references/incident-chaos.md +576 -576
- package/skills/infra/sre-engineer/references/monitoring-alerting.md +424 -424
- package/skills/infra/sre-engineer/references/slo-sli-management.md +238 -238
- package/skills/infra/terraform-engineer/SKILL.md +143 -143
- package/skills/infra/terraform-engineer/references/best-practices.md +583 -583
- package/skills/infra/terraform-engineer/references/module-patterns.md +297 -297
- package/skills/infra/terraform-engineer/references/providers.md +452 -452
- package/skills/infra/terraform-engineer/references/state-management.md +371 -371
- package/skills/infra/terraform-engineer/references/testing.md +486 -486
- package/skills/infra/websocket-engineer/SKILL.md +168 -168
- package/skills/infra/websocket-engineer/references/alternatives.md +391 -391
- package/skills/infra/websocket-engineer/references/patterns.md +400 -400
- package/skills/infra/websocket-engineer/references/protocol.md +195 -195
- package/skills/infra/websocket-engineer/references/scaling.md +333 -333
- package/skills/infra/websocket-engineer/references/security.md +474 -474
- package/skills/java/java-architect/SKILL.md +132 -132
- package/skills/java/java-architect/references/jpa-optimization.md +393 -393
- package/skills/java/java-architect/references/reactive-webflux.md +356 -356
- package/skills/java/java-architect/references/spring-boot-setup.md +269 -269
- package/skills/java/java-architect/references/spring-security.md +445 -445
- package/skills/java/java-architect/references/testing-patterns.md +500 -500
- package/skills/java/kotlin-specialist/SKILL.md +147 -147
- package/skills/java/kotlin-specialist/references/android-compose.md +419 -419
- package/skills/java/kotlin-specialist/references/coroutines-flow.md +276 -276
- package/skills/java/kotlin-specialist/references/dsl-idioms.md +421 -421
- package/skills/java/kotlin-specialist/references/ktor-server.md +426 -426
- package/skills/java/kotlin-specialist/references/multiplatform-kmp.md +380 -380
- package/skills/java/spring-boot-engineer/SKILL.md +195 -195
- package/skills/java/spring-boot-engineer/references/cloud.md +498 -498
- package/skills/java/spring-boot-engineer/references/data.md +381 -381
- package/skills/java/spring-boot-engineer/references/security.md +459 -459
- package/skills/java/spring-boot-engineer/references/testing.md +545 -545
- package/skills/java/spring-boot-engineer/references/web.md +295 -295
- package/skills/javascript/javascript-pro/SKILL.md +132 -132
- package/skills/javascript/javascript-pro/references/async-patterns.md +334 -334
- package/skills/javascript/javascript-pro/references/browser-apis.md +398 -398
- package/skills/javascript/javascript-pro/references/modern-syntax.md +272 -272
- package/skills/javascript/javascript-pro/references/modules.md +357 -357
- package/skills/javascript/javascript-pro/references/node-essentials.md +471 -471
- package/skills/javascript/nestjs-expert/SKILL.md +206 -206
- package/skills/javascript/nestjs-expert/references/authentication.md +166 -166
- package/skills/javascript/nestjs-expert/references/controllers-routing.md +111 -111
- package/skills/javascript/nestjs-expert/references/dtos-validation.md +153 -153
- package/skills/javascript/nestjs-expert/references/migration-from-express.md +1237 -1237
- package/skills/javascript/nestjs-expert/references/services-di.md +140 -140
- package/skills/javascript/nestjs-expert/references/testing-patterns.md +186 -186
- package/skills/javascript/typescript-pro/SKILL.md +145 -145
- package/skills/javascript/typescript-pro/references/advanced-types.md +259 -259
- package/skills/javascript/typescript-pro/references/configuration.md +445 -445
- package/skills/javascript/typescript-pro/references/patterns.md +484 -484
- package/skills/javascript/typescript-pro/references/type-guards.md +352 -352
- package/skills/javascript/typescript-pro/references/utility-types.md +329 -329
- package/skills/php/laravel-specialist/SKILL.md +262 -262
- package/skills/php/laravel-specialist/references/eloquent.md +351 -351
- package/skills/php/laravel-specialist/references/livewire.md +512 -512
- package/skills/php/laravel-specialist/references/queues.md +423 -423
- package/skills/php/laravel-specialist/references/routing.md +362 -362
- package/skills/php/laravel-specialist/references/testing.md +522 -522
- package/skills/php/php-pro/SKILL.md +206 -206
- package/skills/php/php-pro/references/async-patterns.md +412 -412
- package/skills/php/php-pro/references/laravel-patterns.md +377 -377
- package/skills/php/php-pro/references/modern-php-features.md +323 -323
- package/skills/php/php-pro/references/symfony-patterns.md +466 -466
- package/skills/php/php-pro/references/testing-quality.md +466 -466
- package/skills/product/competitive-analysis/SKILL.md +257 -257
- package/skills/product/meeting-notes/SKILL.md +266 -266
- package/skills/product/prd-template/SKILL.md +150 -150
- package/skills/product/stakeholder-update/SKILL.md +225 -225
- package/skills/product/user-research-synthesis/SKILL.md +235 -235
- package/skills/python/django-expert/SKILL.md +162 -162
- package/skills/python/django-expert/references/authentication.md +145 -145
- package/skills/python/django-expert/references/drf-serializers.md +148 -148
- package/skills/python/django-expert/references/models-orm.md +151 -151
- package/skills/python/django-expert/references/testing-django.md +204 -204
- package/skills/python/django-expert/references/viewsets-views.md +153 -153
- package/skills/python/fastapi-expert/SKILL.md +185 -185
- package/skills/python/fastapi-expert/references/async-sqlalchemy.md +146 -146
- package/skills/python/fastapi-expert/references/authentication.md +159 -159
- package/skills/python/fastapi-expert/references/endpoints-routing.md +142 -142
- package/skills/python/fastapi-expert/references/migration-from-django.md +996 -996
- package/skills/python/fastapi-expert/references/pydantic-v2.md +135 -135
- package/skills/python/fastapi-expert/references/testing-async.md +159 -159
- package/skills/python/pandas-pro/SKILL.md +178 -178
- package/skills/python/pandas-pro/references/aggregation-groupby.md +545 -545
- package/skills/python/pandas-pro/references/data-cleaning.md +500 -500
- package/skills/python/pandas-pro/references/dataframe-operations.md +420 -420
- package/skills/python/pandas-pro/references/merging-joining.md +596 -596
- package/skills/python/pandas-pro/references/performance-optimization.md +597 -597
- package/skills/python/python-pro/SKILL.md +177 -177
- package/skills/python/python-pro/references/async-patterns.md +356 -356
- package/skills/python/python-pro/references/packaging.md +460 -460
- package/skills/python/python-pro/references/standard-library.md +378 -378
- package/skills/python/python-pro/references/testing.md +404 -404
- package/skills/python/python-pro/references/type-system.md +290 -290
- package/skills/quality/chaos-engineer/SKILL.md +182 -182
- package/skills/quality/chaos-engineer/references/chaos-tools.md +511 -511
- package/skills/quality/chaos-engineer/references/experiment-design.md +229 -229
- package/skills/quality/chaos-engineer/references/game-days.md +434 -434
- package/skills/quality/chaos-engineer/references/infrastructure-chaos.md +348 -348
- package/skills/quality/chaos-engineer/references/kubernetes-chaos.md +432 -432
- package/skills/quality/code-reviewer/SKILL.md +119 -119
- package/skills/quality/code-reviewer/references/common-issues.md +142 -142
- package/skills/quality/code-reviewer/references/feedback-examples.md +144 -144
- package/skills/quality/code-reviewer/references/receiving-feedback.md +238 -238
- package/skills/quality/code-reviewer/references/report-template.md +109 -109
- package/skills/quality/code-reviewer/references/review-checklist.md +88 -88
- package/skills/quality/code-reviewer/references/spec-compliance-review.md +258 -258
- package/skills/quality/playwright-expert/SKILL.md +169 -169
- package/skills/quality/playwright-expert/references/api-mocking.md +140 -140
- package/skills/quality/playwright-expert/references/configuration.md +155 -155
- package/skills/quality/playwright-expert/references/debugging-flaky.md +150 -150
- package/skills/quality/playwright-expert/references/page-object-model.md +152 -152
- package/skills/quality/playwright-expert/references/selectors-locators.md +119 -119
- package/skills/quality/secure-code-guardian/SKILL.md +191 -191
- package/skills/quality/secure-code-guardian/references/authentication.md +136 -136
- package/skills/quality/secure-code-guardian/references/input-validation.md +146 -146
- package/skills/quality/secure-code-guardian/references/owasp-prevention.md +135 -135
- package/skills/quality/secure-code-guardian/references/security-headers.md +133 -133
- package/skills/quality/secure-code-guardian/references/xss-csrf.md +157 -157
- package/skills/quality/security-reviewer/SKILL.md +103 -103
- package/skills/quality/security-reviewer/references/infrastructure-security.md +268 -268
- package/skills/quality/security-reviewer/references/penetration-testing.md +268 -268
- package/skills/quality/security-reviewer/references/report-template.md +170 -170
- package/skills/quality/security-reviewer/references/sast-tools.md +117 -117
- package/skills/quality/security-reviewer/references/secret-scanning.md +125 -125
- package/skills/quality/security-reviewer/references/vulnerability-patterns.md +152 -152
- package/skills/quality/senior-qa/README.md +196 -196
- package/skills/quality/senior-qa/SKILL.md +399 -399
- package/skills/quality/senior-qa/references/qa_best_practices.md +964 -964
- package/skills/quality/senior-qa/references/test_automation_patterns.md +1009 -1009
- package/skills/quality/senior-qa/references/testing_strategies.md +649 -649
- package/skills/quality/senior-qa/scripts/coverage_analyzer.py +836 -836
- package/skills/quality/senior-qa/scripts/e2e_test_scaffolder.py +820 -820
- package/skills/quality/senior-qa/scripts/test_suite_generator.py +605 -605
- package/skills/quality/tdd-guide/HOW_TO_USE.md +313 -313
- package/skills/quality/tdd-guide/README.md +680 -680
- package/skills/quality/tdd-guide/SKILL.md +122 -122
- package/skills/quality/tdd-guide/assets/expected_output.json +77 -77
- package/skills/quality/tdd-guide/assets/sample_input_python.json +39 -39
- package/skills/quality/tdd-guide/assets/sample_input_typescript.json +36 -36
- package/skills/quality/tdd-guide/references/ci-integration.md +195 -195
- package/skills/quality/tdd-guide/references/framework-guide.md +206 -206
- package/skills/quality/tdd-guide/references/tdd-best-practices.md +128 -128
- package/skills/quality/tdd-guide/scripts/coverage_analyzer.py +434 -434
- package/skills/quality/tdd-guide/scripts/fixture_generator.py +440 -440
- package/skills/quality/tdd-guide/scripts/format_detector.py +384 -384
- package/skills/quality/tdd-guide/scripts/framework_adapter.py +428 -428
- package/skills/quality/tdd-guide/scripts/metrics_calculator.py +456 -456
- package/skills/quality/tdd-guide/scripts/output_formatter.py +354 -354
- package/skills/quality/tdd-guide/scripts/tdd_workflow.py +474 -474
- package/skills/quality/tdd-guide/scripts/test_generator.py +438 -438
- package/skills/quality/test-master/SKILL.md +94 -94
- package/skills/quality/test-master/references/automation-frameworks.md +294 -294
- package/skills/quality/test-master/references/e2e-testing.md +128 -128
- package/skills/quality/test-master/references/integration-testing.md +120 -120
- package/skills/quality/test-master/references/performance-testing.md +118 -118
- package/skills/quality/test-master/references/qa-methodology.md +247 -247
- package/skills/quality/test-master/references/security-testing.md +127 -127
- package/skills/quality/test-master/references/tdd-iron-laws.md +174 -174
- package/skills/quality/test-master/references/test-reports.md +104 -104
- package/skills/quality/test-master/references/testing-anti-patterns.md +231 -231
- package/skills/quality/test-master/references/unit-testing.md +113 -113
- package/skills/ruby/rails-expert/SKILL.md +154 -154
- package/skills/ruby/rails-expert/references/active-record.md +244 -244
- package/skills/ruby/rails-expert/references/api-development.md +401 -401
- package/skills/ruby/rails-expert/references/background-jobs.md +272 -272
- package/skills/ruby/rails-expert/references/hotwire-turbo.md +228 -228
- package/skills/ruby/rails-expert/references/rspec-testing.md +367 -367
- package/skills/swift/swift-expert/SKILL.md +163 -163
- package/skills/swift/swift-expert/references/async-concurrency.md +360 -360
- package/skills/swift/swift-expert/references/memory-performance.md +377 -377
- package/skills/swift/swift-expert/references/protocol-oriented.md +354 -354
- package/skills/swift/swift-expert/references/swiftui-patterns.md +291 -291
- package/skills/swift/swift-expert/references/testing-patterns.md +399 -399
- package/skills/workflow/brainstorming/SKILL.md +164 -164
- package/skills/workflow/brainstorming/scripts/frame-template.html +214 -214
- package/skills/workflow/brainstorming/scripts/helper.js +88 -88
- package/skills/workflow/brainstorming/scripts/server.cjs +354 -354
- package/skills/workflow/brainstorming/scripts/start-server.sh +148 -148
- package/skills/workflow/brainstorming/scripts/stop-server.sh +56 -56
- package/skills/workflow/brainstorming/spec-document-reviewer-prompt.md +49 -49
- package/skills/workflow/brainstorming/visual-companion.md +287 -287
- package/skills/workflow/documentation/SKILL.md +45 -45
- package/skills/workflow/entropy-management/SKILL.md +115 -115
- package/skills/workflow/executing-plans/SKILL.md +70 -70
- package/skills/workflow/finishing-a-development-branch/SKILL.md +200 -200
- package/skills/workflow/receiving-code-review/SKILL.md +213 -213
- package/skills/workflow/requesting-code-review/SKILL.md +105 -105
- package/skills/workflow/requesting-code-review/code-reviewer.md +146 -146
- package/skills/workflow/requirement-engineering/SKILL.md +111 -111
- package/skills/workflow/systematic-debugging/CREATION-LOG.md +119 -119
- package/skills/workflow/systematic-debugging/SKILL.md +296 -296
- package/skills/workflow/systematic-debugging/condition-based-waiting-example.ts +158 -158
- package/skills/workflow/systematic-debugging/condition-based-waiting.md +115 -115
- package/skills/workflow/systematic-debugging/defense-in-depth.md +122 -122
- package/skills/workflow/systematic-debugging/find-polluter.sh +63 -63
- package/skills/workflow/systematic-debugging/root-cause-tracing.md +169 -169
- package/skills/workflow/systematic-debugging/test-academic.md +14 -14
- package/skills/workflow/systematic-debugging/test-pressure-1.md +58 -58
- package/skills/workflow/systematic-debugging/test-pressure-2.md +68 -68
- package/skills/workflow/systematic-debugging/test-pressure-3.md +69 -69
- package/skills/workflow/using-git-worktrees/SKILL.md +218 -218
- package/skills/workflow/verification-before-completion/SKILL.md +139 -139
- package/skills/workflow/writing-plans/SKILL.md +151 -151
- package/skills/workflow/writing-plans/plan-document-reviewer-prompt.md +49 -49
- package/skills/workflow/writing-skills/SKILL.md +655 -655
- package/skills/workflow/writing-skills/anthropic-best-practices.md +1150 -1150
- package/skills/workflow/writing-skills/examples/CLAUDE_MD_TESTING.md +189 -189
- package/skills/workflow/writing-skills/persuasion-principles.md +187 -187
- package/skills/workflow/writing-skills/render-graphs.js +168 -168
- package/skills/workflow/writing-skills/testing-skills-with-subagents.md +384 -384
|
@@ -1,543 +1,543 @@
|
|
|
1
|
-
# Partitioning and Caching
|
|
2
|
-
|
|
3
|
-
---
|
|
4
|
-
|
|
5
|
-
## Partitioning Fundamentals
|
|
6
|
-
|
|
7
|
-
### Why Partitioning Matters
|
|
8
|
-
|
|
9
|
-
- **Parallelism**: Each partition runs on a separate task
|
|
10
|
-
- **Data locality**: Minimize data movement across network
|
|
11
|
-
- **Memory efficiency**: Right-sized partitions prevent OOM
|
|
12
|
-
- **Join performance**: Co-partitioned data avoids shuffle
|
|
13
|
-
|
|
14
|
-
### Partition Count Guidelines
|
|
15
|
-
|
|
16
|
-
```python
|
|
17
|
-
# Rule of thumb: 2-4 partitions per CPU core
|
|
18
|
-
# For 100 executor cores: 200-400 partitions
|
|
19
|
-
|
|
20
|
-
# Check current partitions
|
|
21
|
-
print(f"Number of partitions: {df.rdd.getNumPartitions()}")
|
|
22
|
-
|
|
23
|
-
# Recommended formula
|
|
24
|
-
total_cores = num_executors * cores_per_executor
|
|
25
|
-
recommended_partitions = total_cores * 2 to 4
|
|
26
|
-
|
|
27
|
-
# Target partition size: 128MB - 256MB per partition
|
|
28
|
-
# For 100GB data with 128MB target: ~800 partitions
|
|
29
|
-
```
|
|
30
|
-
|
|
31
|
-
### Optimal Partition Sizes
|
|
32
|
-
|
|
33
|
-
| Data Volume | Target Partition Size | Partition Count |
|
|
34
|
-
|-------------|----------------------|-----------------|
|
|
35
|
-
| < 1GB | 64MB | 8-16 |
|
|
36
|
-
| 1-10GB | 128MB | 8-80 |
|
|
37
|
-
| 10-100GB | 128-256MB | 40-800 |
|
|
38
|
-
| 100GB-1TB | 256MB | 400-4000 |
|
|
39
|
-
| > 1TB | 256MB | 4000+ |
|
|
40
|
-
|
|
41
|
-
---
|
|
42
|
-
|
|
43
|
-
## DataFrame Partitioning
|
|
44
|
-
|
|
45
|
-
### Repartition (Full Shuffle)
|
|
46
|
-
|
|
47
|
-
```python
|
|
48
|
-
from pyspark.sql import functions as F
|
|
49
|
-
|
|
50
|
-
# Repartition to specific number
|
|
51
|
-
df_repart = df.repartition(200)
|
|
52
|
-
|
|
53
|
-
# Repartition by column(s) - same keys go to same partition
|
|
54
|
-
df_repart = df.repartition("user_id")
|
|
55
|
-
df_repart = df.repartition("user_id", "date")
|
|
56
|
-
|
|
57
|
-
# Repartition with count and columns
|
|
58
|
-
df_repart = df.repartition(100, "user_id")
|
|
59
|
-
|
|
60
|
-
# Range partitioning (for sorted access patterns)
|
|
61
|
-
df_range = df.repartitionByRange(100, "date")
|
|
62
|
-
```
|
|
63
|
-
|
|
64
|
-
```scala
|
|
65
|
-
// Scala repartition
|
|
66
|
-
val dfRepart = df.repartition(200)
|
|
67
|
-
val dfByCol = df.repartition($"user_id")
|
|
68
|
-
val dfRange = df.repartitionByRange(100, $"date")
|
|
69
|
-
```
|
|
70
|
-
|
|
71
|
-
### Coalesce (No Shuffle)
|
|
72
|
-
|
|
73
|
-
```python
|
|
74
|
-
# Reduce partitions without shuffle - efficient!
|
|
75
|
-
# Use after filtering reduces data significantly
|
|
76
|
-
df_coalesced = df.coalesce(50)
|
|
77
|
-
|
|
78
|
-
# Common pattern: filter then coalesce
|
|
79
|
-
df_filtered = df.filter(F.col("active") == True)
|
|
80
|
-
# If filter reduced data by 80%, reduce partitions too
|
|
81
|
-
df_optimized = df_filtered.coalesce(40) # From 200 to 40
|
|
82
|
-
```
|
|
83
|
-
|
|
84
|
-
**When to use:**
|
|
85
|
-
- `repartition(n)`: Increase partitions, need even distribution, partition by column
|
|
86
|
-
- `coalesce(n)`: Decrease partitions only (no shuffle benefit)
|
|
87
|
-
- `repartitionByRange()`: Need sorted partitions for range queries
|
|
88
|
-
|
|
89
|
-
### Checking Partition Distribution
|
|
90
|
-
|
|
91
|
-
```python
|
|
92
|
-
from pyspark.sql import functions as F
|
|
93
|
-
|
|
94
|
-
# Check partition count
|
|
95
|
-
print(f"Partitions: {df.rdd.getNumPartitions()}")
|
|
96
|
-
|
|
97
|
-
# Check partition sizes (row counts)
|
|
98
|
-
partition_counts = df.withColumn("partition_id", F.spark_partition_id()) \
|
|
99
|
-
.groupBy("partition_id") \
|
|
100
|
-
.count() \
|
|
101
|
-
.orderBy("partition_id")
|
|
102
|
-
|
|
103
|
-
partition_counts.show()
|
|
104
|
-
|
|
105
|
-
# Get partition statistics
|
|
106
|
-
stats = partition_counts.agg(
|
|
107
|
-
F.min("count").alias("min_rows"),
|
|
108
|
-
F.max("count").alias("max_rows"),
|
|
109
|
-
F.avg("count").alias("avg_rows"),
|
|
110
|
-
F.stddev("count").alias("stddev")
|
|
111
|
-
)
|
|
112
|
-
stats.show()
|
|
113
|
-
|
|
114
|
-
# Identify skew: max/avg ratio > 3 indicates skew
|
|
115
|
-
```
|
|
116
|
-
|
|
117
|
-
---
|
|
118
|
-
|
|
119
|
-
## Shuffle Partitions
|
|
120
|
-
|
|
121
|
-
### Configuration
|
|
122
|
-
|
|
123
|
-
```python
|
|
124
|
-
# Default shuffle partitions (200) - often suboptimal
|
|
125
|
-
spark.conf.set("spark.sql.shuffle.partitions", 200)
|
|
126
|
-
|
|
127
|
-
# For small data (<10GB), reduce
|
|
128
|
-
spark.conf.set("spark.sql.shuffle.partitions", 50)
|
|
129
|
-
|
|
130
|
-
# For large data (>100GB), increase
|
|
131
|
-
spark.conf.set("spark.sql.shuffle.partitions", 2000)
|
|
132
|
-
|
|
133
|
-
# Adaptive Query Execution (Spark 3.0+) - dynamic partition sizing
|
|
134
|
-
spark.conf.set("spark.sql.adaptive.enabled", "true")
|
|
135
|
-
spark.conf.set("spark.sql.adaptive.coalescePartitions.enabled", "true")
|
|
136
|
-
spark.conf.set("spark.sql.adaptive.coalescePartitions.minPartitionSize", "64MB")
|
|
137
|
-
spark.conf.set("spark.sql.adaptive.advisoryPartitionSizeInBytes", "128MB")
|
|
138
|
-
```
|
|
139
|
-
|
|
140
|
-
### AQE Automatic Optimization (Spark 3.x)
|
|
141
|
-
|
|
142
|
-
```python
|
|
143
|
-
# Enable full AQE suite
|
|
144
|
-
spark.conf.set("spark.sql.adaptive.enabled", "true")
|
|
145
|
-
|
|
146
|
-
# Auto-coalesce shuffle partitions
|
|
147
|
-
spark.conf.set("spark.sql.adaptive.coalescePartitions.enabled", "true")
|
|
148
|
-
spark.conf.set("spark.sql.adaptive.coalescePartitions.parallelismFirst", "false")
|
|
149
|
-
|
|
150
|
-
# Handle skewed partitions automatically
|
|
151
|
-
spark.conf.set("spark.sql.adaptive.skewJoin.enabled", "true")
|
|
152
|
-
spark.conf.set("spark.sql.adaptive.skewJoin.skewedPartitionFactor", 5)
|
|
153
|
-
spark.conf.set("spark.sql.adaptive.skewJoin.skewedPartitionThresholdInBytes", "256MB")
|
|
154
|
-
|
|
155
|
-
# Local shuffle reader (avoid remote reads when possible)
|
|
156
|
-
spark.conf.set("spark.sql.adaptive.localShuffleReader.enabled", "true")
|
|
157
|
-
```
|
|
158
|
-
|
|
159
|
-
**Spark UI Check:** With AQE, check "Adaptive" badge in SQL tab. View coalesced partition counts in stage details.
|
|
160
|
-
|
|
161
|
-
---
|
|
162
|
-
|
|
163
|
-
## Caching and Persistence
|
|
164
|
-
|
|
165
|
-
### When to Cache
|
|
166
|
-
|
|
167
|
-
**Cache when:**
|
|
168
|
-
- DataFrame is reused multiple times in same job
|
|
169
|
-
- DataFrame is expensive to compute (complex joins/aggregations)
|
|
170
|
-
- Iterative algorithms (ML training loops)
|
|
171
|
-
- Interactive exploration in notebooks
|
|
172
|
-
|
|
173
|
-
**Do NOT cache when:**
|
|
174
|
-
- DataFrame used only once
|
|
175
|
-
- Data doesn't fit in cluster memory
|
|
176
|
-
- Source data is already fast (local SSD, columnar formats)
|
|
177
|
-
- Storage level causes excessive GC
|
|
178
|
-
|
|
179
|
-
### Persistence Levels
|
|
180
|
-
|
|
181
|
-
```python
|
|
182
|
-
from pyspark import StorageLevel
|
|
183
|
-
|
|
184
|
-
# Memory only (default for cache())
|
|
185
|
-
df.cache() # Equivalent to persist(MEMORY_AND_DISK)
|
|
186
|
-
df.persist() # Same as cache()
|
|
187
|
-
|
|
188
|
-
# Specific storage levels
|
|
189
|
-
df.persist(StorageLevel.MEMORY_ONLY) # Fast, may lose partitions
|
|
190
|
-
df.persist(StorageLevel.MEMORY_AND_DISK) # Spill to disk if needed
|
|
191
|
-
df.persist(StorageLevel.MEMORY_ONLY_SER) # Serialized, less memory, slower
|
|
192
|
-
df.persist(StorageLevel.MEMORY_AND_DISK_SER) # Serialized with disk spill
|
|
193
|
-
df.persist(StorageLevel.DISK_ONLY) # Only disk, slowest
|
|
194
|
-
df.persist(StorageLevel.OFF_HEAP) # Off-heap memory
|
|
195
|
-
|
|
196
|
-
# With replication (for fault tolerance)
|
|
197
|
-
df.persist(StorageLevel.MEMORY_AND_DISK_2) # 2x replication
|
|
198
|
-
|
|
199
|
-
# Unpersist when done
|
|
200
|
-
df.unpersist()
|
|
201
|
-
df.unpersist(blocking=True) # Wait for completion
|
|
202
|
-
```
|
|
203
|
-
|
|
204
|
-
```scala
|
|
205
|
-
// Scala persistence
|
|
206
|
-
import org.apache.spark.storage.StorageLevel
|
|
207
|
-
|
|
208
|
-
df.cache()
|
|
209
|
-
df.persist(StorageLevel.MEMORY_AND_DISK_SER)
|
|
210
|
-
df.unpersist()
|
|
211
|
-
```
|
|
212
|
-
|
|
213
|
-
### Storage Level Selection Guide
|
|
214
|
-
|
|
215
|
-
| Storage Level | Use When |
|
|
216
|
-
|---------------|----------|
|
|
217
|
-
| MEMORY_ONLY | Enough memory, need fastest access |
|
|
218
|
-
| MEMORY_AND_DISK | Default, safe for most cases |
|
|
219
|
-
| MEMORY_ONLY_SER | Memory constrained, CPU available |
|
|
220
|
-
| MEMORY_AND_DISK_SER | Large data, memory constrained |
|
|
221
|
-
| DISK_ONLY | Very large data, memory scarce |
|
|
222
|
-
| OFF_HEAP | Using Tungsten off-heap memory |
|
|
223
|
-
|
|
224
|
-
### Caching Best Practices
|
|
225
|
-
|
|
226
|
-
```python
|
|
227
|
-
# Pattern 1: Cache after expensive transformation
|
|
228
|
-
expensive_df = source_df \
|
|
229
|
-
.join(lookup_df, "key") \
|
|
230
|
-
.groupBy("category").agg(F.sum("amount"))
|
|
231
|
-
|
|
232
|
-
expensive_df.cache()
|
|
233
|
-
|
|
234
|
-
# Trigger caching with action
|
|
235
|
-
expensive_df.count()
|
|
236
|
-
|
|
237
|
-
# Reuse cached data
|
|
238
|
-
result1 = expensive_df.filter(F.col("category") == "A")
|
|
239
|
-
result2 = expensive_df.filter(F.col("category") == "B")
|
|
240
|
-
|
|
241
|
-
# Clean up
|
|
242
|
-
expensive_df.unpersist()
|
|
243
|
-
|
|
244
|
-
# Pattern 2: Cache at checkpoint in iterative algorithm
|
|
245
|
-
for iteration in range(100):
|
|
246
|
-
df = df.transform(update_function)
|
|
247
|
-
if iteration % 10 == 0:
|
|
248
|
-
df.cache()
|
|
249
|
-
df.count() # Materialize
|
|
250
|
-
df.unpersist() # Clean previous
|
|
251
|
-
|
|
252
|
-
# Pattern 3: Checkpoint to break lineage (long pipelines)
|
|
253
|
-
spark.sparkContext.setCheckpointDir("hdfs://path/checkpoints/")
|
|
254
|
-
df.checkpoint() # Truncates lineage, saves to reliable storage
|
|
255
|
-
```
|
|
256
|
-
|
|
257
|
-
### Monitoring Cache Usage
|
|
258
|
-
|
|
259
|
-
```python
|
|
260
|
-
# Check if DataFrame is cached
|
|
261
|
-
print(df.storageLevel) # StorageLevel(False, False, False, False, 1) = not cached
|
|
262
|
-
|
|
263
|
-
# Check storage tab in Spark UI for:
|
|
264
|
-
# - Size in Memory
|
|
265
|
-
# - Size on Disk
|
|
266
|
-
# - Fraction Cached (should be 100%)
|
|
267
|
-
```
|
|
268
|
-
|
|
269
|
-
**Spark UI Check:** Storage tab shows cached RDDs/DataFrames. Monitor "Fraction Cached" - if < 100%, memory is insufficient.
|
|
270
|
-
|
|
271
|
-
---
|
|
272
|
-
|
|
273
|
-
## Broadcast Variables
|
|
274
|
-
|
|
275
|
-
### When to Use Broadcast
|
|
276
|
-
|
|
277
|
-
- Small lookup tables (< 200MB)
|
|
278
|
-
- Dimension tables joined to large fact tables
|
|
279
|
-
- Configuration data used across all tasks
|
|
280
|
-
- Avoiding shuffle in map-side joins
|
|
281
|
-
|
|
282
|
-
### DataFrame Broadcast Join
|
|
283
|
-
|
|
284
|
-
```python
|
|
285
|
-
from pyspark.sql.functions import broadcast
|
|
286
|
-
|
|
287
|
-
# Explicit broadcast hint
|
|
288
|
-
large_df = spark.read.parquet("s3://bucket/transactions/") # 100GB
|
|
289
|
-
small_df = spark.read.parquet("s3://bucket/categories/") # 50MB
|
|
290
|
-
|
|
291
|
-
# Broadcast small table for efficient join
|
|
292
|
-
result = large_df.join(broadcast(small_df), "category_id")
|
|
293
|
-
|
|
294
|
-
# Auto-broadcast threshold configuration
|
|
295
|
-
spark.conf.set("spark.sql.autoBroadcastJoinThreshold", 100 * 1024 * 1024) # 100MB
|
|
296
|
-
|
|
297
|
-
# Disable auto-broadcast (force sort-merge join)
|
|
298
|
-
spark.conf.set("spark.sql.autoBroadcastJoinThreshold", -1)
|
|
299
|
-
```
|
|
300
|
-
|
|
301
|
-
### RDD Broadcast Variables
|
|
302
|
-
|
|
303
|
-
```python
|
|
304
|
-
# Create broadcast variable
|
|
305
|
-
lookup_dict = {"A": 1, "B": 2, "C": 3}
|
|
306
|
-
broadcast_lookup = spark.sparkContext.broadcast(lookup_dict)
|
|
307
|
-
|
|
308
|
-
# Use in transformation
|
|
309
|
-
def enrich_with_lookup(row):
|
|
310
|
-
lookup = broadcast_lookup.value
|
|
311
|
-
return Row(
|
|
312
|
-
id=row.id,
|
|
313
|
-
code=row.code,
|
|
314
|
-
value=lookup.get(row.code, 0)
|
|
315
|
-
)
|
|
316
|
-
|
|
317
|
-
enriched_rdd = df.rdd.map(enrich_with_lookup)
|
|
318
|
-
|
|
319
|
-
# Clean up
|
|
320
|
-
broadcast_lookup.unpersist()
|
|
321
|
-
broadcast_lookup.destroy()
|
|
322
|
-
```
|
|
323
|
-
|
|
324
|
-
### Broadcast Size Limits
|
|
325
|
-
|
|
326
|
-
```python
|
|
327
|
-
# Maximum broadcast size (default 8GB, adjustable)
|
|
328
|
-
spark.conf.set("spark.sql.autoBroadcastJoinThreshold", 200 * 1024 * 1024) # 200MB
|
|
329
|
-
|
|
330
|
-
# For larger broadcasts
|
|
331
|
-
spark.conf.set("spark.driver.maxResultSize", "4g")
|
|
332
|
-
|
|
333
|
-
# Monitor broadcast time in Spark UI
|
|
334
|
-
# Long broadcast time indicates table too large
|
|
335
|
-
```
|
|
336
|
-
|
|
337
|
-
**Warning:** Broadcasting tables > 200MB can cause driver OOM and slow broadcast. Use sort-merge join instead.
|
|
338
|
-
|
|
339
|
-
---
|
|
340
|
-
|
|
341
|
-
## Partitioning Strategies for Common Patterns
|
|
342
|
-
|
|
343
|
-
### Time-Series Data
|
|
344
|
-
|
|
345
|
-
```python
|
|
346
|
-
# Partition by date for time-range queries
|
|
347
|
-
df_partitioned = df.repartition("date")
|
|
348
|
-
|
|
349
|
-
# Range partition for ordered access
|
|
350
|
-
df_range = df.repartitionByRange(365, "date") # One year
|
|
351
|
-
|
|
352
|
-
# Write partitioned by date
|
|
353
|
-
df.write.partitionBy("year", "month", "day").parquet("s3://bucket/data/")
|
|
354
|
-
|
|
355
|
-
# Read with partition pruning
|
|
356
|
-
df = spark.read.parquet("s3://bucket/data/") \
|
|
357
|
-
.filter(F.col("year") == 2024) # Only reads 2024 partitions
|
|
358
|
-
```
|
|
359
|
-
|
|
360
|
-
### User/Entity Data
|
|
361
|
-
|
|
362
|
-
```python
|
|
363
|
-
# Partition by user_id for user-specific queries
|
|
364
|
-
df_user_partitioned = df.repartition(1000, "user_id")
|
|
365
|
-
|
|
366
|
-
# Co-partition for efficient joins
|
|
367
|
-
users_partitioned = users.repartition(1000, "user_id")
|
|
368
|
-
orders_partitioned = orders.repartition(1000, "user_id")
|
|
369
|
-
|
|
370
|
-
# Join without shuffle (if partitioners match)
|
|
371
|
-
joined = users_partitioned.join(orders_partitioned, "user_id")
|
|
372
|
-
```
|
|
373
|
-
|
|
374
|
-
### Skewed Data
|
|
375
|
-
|
|
376
|
-
```python
|
|
377
|
-
# Salt skewed keys
|
|
378
|
-
salt_buckets = 10
|
|
379
|
-
|
|
380
|
-
# Add salt to skewed table
|
|
381
|
-
salted_df = large_df.withColumn(
|
|
382
|
-
"salted_key",
|
|
383
|
-
F.concat(
|
|
384
|
-
F.col("join_key"),
|
|
385
|
-
F.lit("_"),
|
|
386
|
-
(F.monotonically_increasing_id() % salt_buckets).cast("string")
|
|
387
|
-
)
|
|
388
|
-
)
|
|
389
|
-
|
|
390
|
-
# Explode small table to match
|
|
391
|
-
from pyspark.sql.functions import explode, array, lit
|
|
392
|
-
|
|
393
|
-
small_exploded = small_df.withColumn(
|
|
394
|
-
"salt",
|
|
395
|
-
explode(array([lit(i) for i in range(salt_buckets)]))
|
|
396
|
-
).withColumn(
|
|
397
|
-
"salted_key",
|
|
398
|
-
F.concat(F.col("join_key"), F.lit("_"), F.col("salt").cast("string"))
|
|
399
|
-
)
|
|
400
|
-
|
|
401
|
-
# Join on salted key
|
|
402
|
-
result = salted_df.join(small_exploded, "salted_key")
|
|
403
|
-
```
|
|
404
|
-
|
|
405
|
-
---
|
|
406
|
-
|
|
407
|
-
## File Partitioning (Write Optimization)
|
|
408
|
-
|
|
409
|
-
### Hive-Style Partitioning
|
|
410
|
-
|
|
411
|
-
```python
|
|
412
|
-
# Write with partitioning
|
|
413
|
-
df.write \
|
|
414
|
-
.mode("overwrite") \
|
|
415
|
-
.partitionBy("year", "month") \
|
|
416
|
-
.parquet("s3://bucket/data/")
|
|
417
|
-
|
|
418
|
-
# Result directory structure:
|
|
419
|
-
# s3://bucket/data/year=2024/month=01/part-*.parquet
|
|
420
|
-
# s3://bucket/data/year=2024/month=02/part-*.parquet
|
|
421
|
-
|
|
422
|
-
# Read with partition discovery
|
|
423
|
-
df = spark.read.parquet("s3://bucket/data/")
|
|
424
|
-
# Columns year, month automatically added from path
|
|
425
|
-
```
|
|
426
|
-
|
|
427
|
-
### Bucketing (Hash-Based File Partitioning)
|
|
428
|
-
|
|
429
|
-
```python
|
|
430
|
-
# Write bucketed table for optimized joins
|
|
431
|
-
df.write \
|
|
432
|
-
.mode("overwrite") \
|
|
433
|
-
.bucketBy(100, "user_id") \
|
|
434
|
-
.sortBy("timestamp") \
|
|
435
|
-
.saveAsTable("bucketed_orders")
|
|
436
|
-
|
|
437
|
-
# Read bucketed table
|
|
438
|
-
orders = spark.table("bucketed_orders")
|
|
439
|
-
users = spark.table("bucketed_users") # Same bucket count
|
|
440
|
-
|
|
441
|
-
# Bucket join - no shuffle if buckets match
|
|
442
|
-
result = orders.join(users, "user_id")
|
|
443
|
-
```
|
|
444
|
-
|
|
445
|
-
**Note:** Bucketing requires Hive metastore and saveAsTable. Doesn't work with direct file writes.
|
|
446
|
-
|
|
447
|
-
### Controlling Output Files
|
|
448
|
-
|
|
449
|
-
```python
|
|
450
|
-
# Control number of output files
|
|
451
|
-
# One file per partition
|
|
452
|
-
df.coalesce(1).write.parquet("s3://bucket/output/")
|
|
453
|
-
|
|
454
|
-
# Multiple files per partition (for large partitions)
|
|
455
|
-
df.repartition(100).write.parquet("s3://bucket/output/")
|
|
456
|
-
|
|
457
|
-
# Max records per file
|
|
458
|
-
df.write \
|
|
459
|
-
.option("maxRecordsPerFile", 1000000) \
|
|
460
|
-
.parquet("s3://bucket/output/")
|
|
461
|
-
```
|
|
462
|
-
|
|
463
|
-
---
|
|
464
|
-
|
|
465
|
-
## Spark UI Analysis for Partitioning/Caching
|
|
466
|
-
|
|
467
|
-
### Jobs Tab
|
|
468
|
-
|
|
469
|
-
- Check if cached data shows "(cached)" in DAG
|
|
470
|
-
- Look for skipped stages (using cached data)
|
|
471
|
-
|
|
472
|
-
### Stages Tab
|
|
473
|
-
|
|
474
|
-
- **Shuffle Write Size**: Large values indicate repartition opportunities
|
|
475
|
-
- **Shuffle Read Size**: Should be similar across tasks (no skew)
|
|
476
|
-
- **Task Duration Distribution**: Wide variance indicates partition imbalance
|
|
477
|
-
|
|
478
|
-
### Storage Tab
|
|
479
|
-
|
|
480
|
-
- **Size in Memory**: Actual cached size
|
|
481
|
-
- **Size on Disk**: Spilled size
|
|
482
|
-
- **Fraction Cached**: Should be 100% if memory sufficient
|
|
483
|
-
|
|
484
|
-
### SQL Tab
|
|
485
|
-
|
|
486
|
-
- Look for "BroadcastExchange" - indicates broadcast join
|
|
487
|
-
- Look for "ShuffleExchange" - indicates data movement
|
|
488
|
-
- Check "Rows Output" at each stage for data flow
|
|
489
|
-
|
|
490
|
-
---
|
|
491
|
-
|
|
492
|
-
## Common Anti-Patterns
|
|
493
|
-
|
|
494
|
-
```python
|
|
495
|
-
# BAD: Caching without measuring benefit
|
|
496
|
-
for table in all_tables:
|
|
497
|
-
spark.read.parquet(table).cache() # Wastes memory
|
|
498
|
-
|
|
499
|
-
# GOOD: Cache only if reused
|
|
500
|
-
expensive_df.cache()
|
|
501
|
-
result1 = expensive_df.groupBy("a").count()
|
|
502
|
-
result2 = expensive_df.groupBy("b").count()
|
|
503
|
-
expensive_df.unpersist()
|
|
504
|
-
|
|
505
|
-
# BAD: Too many small partitions
|
|
506
|
-
df.repartition(10000) # Creates scheduling overhead
|
|
507
|
-
|
|
508
|
-
# GOOD: Right-size partitions (128MB-256MB each)
|
|
509
|
-
df.repartition(100)
|
|
510
|
-
|
|
511
|
-
# BAD: Too few partitions for large data
|
|
512
|
-
df.coalesce(1) # Single partition can't parallelize
|
|
513
|
-
|
|
514
|
-
# GOOD: Maintain parallelism
|
|
515
|
-
df.coalesce(max(1, target_size))
|
|
516
|
-
|
|
517
|
-
# BAD: Repartition before filter
|
|
518
|
-
df.repartition(1000).filter(F.col("active") == True) # Shuffles then filters
|
|
519
|
-
|
|
520
|
-
# GOOD: Filter then coalesce
|
|
521
|
-
df.filter(F.col("active") == True).coalesce(100) # Filter first, then resize
|
|
522
|
-
|
|
523
|
-
# BAD: Broadcasting large table
|
|
524
|
-
result = large.join(broadcast(also_large), "key") # OOM risk
|
|
525
|
-
|
|
526
|
-
# GOOD: Let Spark decide or use sort-merge
|
|
527
|
-
result = large.join(also_large, "key") # Sort-merge join
|
|
528
|
-
```
|
|
529
|
-
|
|
530
|
-
---
|
|
531
|
-
|
|
532
|
-
## Best Practices Summary
|
|
533
|
-
|
|
534
|
-
1. **Target 128-256MB partitions** - Not too small (overhead) or large (OOM)
|
|
535
|
-
2. **Use 2-4 partitions per core** - Maximize parallelism
|
|
536
|
-
3. **Enable AQE in Spark 3.x** - Automatic partition optimization
|
|
537
|
-
4. **Cache only reused DataFrames** - Measure before caching everything
|
|
538
|
-
5. **Use MEMORY_AND_DISK** - Safe default storage level
|
|
539
|
-
6. **Broadcast tables < 200MB** - Avoid shuffle for small dimension tables
|
|
540
|
-
7. **Coalesce after filters** - Reduce partitions when data shrinks
|
|
541
|
-
8. **Repartition for joins** - Co-partition related tables
|
|
542
|
-
9. **Partition writes by filter columns** - Enable partition pruning
|
|
543
|
-
10. **Monitor Storage tab** - Ensure cache fits in memory
|
|
1
|
+
# Partitioning and Caching
|
|
2
|
+
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
## Partitioning Fundamentals
|
|
6
|
+
|
|
7
|
+
### Why Partitioning Matters
|
|
8
|
+
|
|
9
|
+
- **Parallelism**: Each partition runs on a separate task
|
|
10
|
+
- **Data locality**: Minimize data movement across network
|
|
11
|
+
- **Memory efficiency**: Right-sized partitions prevent OOM
|
|
12
|
+
- **Join performance**: Co-partitioned data avoids shuffle
|
|
13
|
+
|
|
14
|
+
### Partition Count Guidelines
|
|
15
|
+
|
|
16
|
+
```python
|
|
17
|
+
# Rule of thumb: 2-4 partitions per CPU core
|
|
18
|
+
# For 100 executor cores: 200-400 partitions
|
|
19
|
+
|
|
20
|
+
# Check current partitions
|
|
21
|
+
print(f"Number of partitions: {df.rdd.getNumPartitions()}")
|
|
22
|
+
|
|
23
|
+
# Recommended formula
|
|
24
|
+
total_cores = num_executors * cores_per_executor
|
|
25
|
+
recommended_partitions = total_cores * 2 to 4
|
|
26
|
+
|
|
27
|
+
# Target partition size: 128MB - 256MB per partition
|
|
28
|
+
# For 100GB data with 128MB target: ~800 partitions
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
### Optimal Partition Sizes
|
|
32
|
+
|
|
33
|
+
| Data Volume | Target Partition Size | Partition Count |
|
|
34
|
+
|-------------|----------------------|-----------------|
|
|
35
|
+
| < 1GB | 64MB | 8-16 |
|
|
36
|
+
| 1-10GB | 128MB | 8-80 |
|
|
37
|
+
| 10-100GB | 128-256MB | 40-800 |
|
|
38
|
+
| 100GB-1TB | 256MB | 400-4000 |
|
|
39
|
+
| > 1TB | 256MB | 4000+ |
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## DataFrame Partitioning
|
|
44
|
+
|
|
45
|
+
### Repartition (Full Shuffle)
|
|
46
|
+
|
|
47
|
+
```python
|
|
48
|
+
from pyspark.sql import functions as F
|
|
49
|
+
|
|
50
|
+
# Repartition to specific number
|
|
51
|
+
df_repart = df.repartition(200)
|
|
52
|
+
|
|
53
|
+
# Repartition by column(s) - same keys go to same partition
|
|
54
|
+
df_repart = df.repartition("user_id")
|
|
55
|
+
df_repart = df.repartition("user_id", "date")
|
|
56
|
+
|
|
57
|
+
# Repartition with count and columns
|
|
58
|
+
df_repart = df.repartition(100, "user_id")
|
|
59
|
+
|
|
60
|
+
# Range partitioning (for sorted access patterns)
|
|
61
|
+
df_range = df.repartitionByRange(100, "date")
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
```scala
|
|
65
|
+
// Scala repartition
|
|
66
|
+
val dfRepart = df.repartition(200)
|
|
67
|
+
val dfByCol = df.repartition($"user_id")
|
|
68
|
+
val dfRange = df.repartitionByRange(100, $"date")
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### Coalesce (No Shuffle)
|
|
72
|
+
|
|
73
|
+
```python
|
|
74
|
+
# Reduce partitions without shuffle - efficient!
|
|
75
|
+
# Use after filtering reduces data significantly
|
|
76
|
+
df_coalesced = df.coalesce(50)
|
|
77
|
+
|
|
78
|
+
# Common pattern: filter then coalesce
|
|
79
|
+
df_filtered = df.filter(F.col("active") == True)
|
|
80
|
+
# If filter reduced data by 80%, reduce partitions too
|
|
81
|
+
df_optimized = df_filtered.coalesce(40) # From 200 to 40
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
**When to use:**
|
|
85
|
+
- `repartition(n)`: Increase partitions, need even distribution, partition by column
|
|
86
|
+
- `coalesce(n)`: Decrease partitions only (no shuffle benefit)
|
|
87
|
+
- `repartitionByRange()`: Need sorted partitions for range queries
|
|
88
|
+
|
|
89
|
+
### Checking Partition Distribution
|
|
90
|
+
|
|
91
|
+
```python
|
|
92
|
+
from pyspark.sql import functions as F
|
|
93
|
+
|
|
94
|
+
# Check partition count
|
|
95
|
+
print(f"Partitions: {df.rdd.getNumPartitions()}")
|
|
96
|
+
|
|
97
|
+
# Check partition sizes (row counts)
|
|
98
|
+
partition_counts = df.withColumn("partition_id", F.spark_partition_id()) \
|
|
99
|
+
.groupBy("partition_id") \
|
|
100
|
+
.count() \
|
|
101
|
+
.orderBy("partition_id")
|
|
102
|
+
|
|
103
|
+
partition_counts.show()
|
|
104
|
+
|
|
105
|
+
# Get partition statistics
|
|
106
|
+
stats = partition_counts.agg(
|
|
107
|
+
F.min("count").alias("min_rows"),
|
|
108
|
+
F.max("count").alias("max_rows"),
|
|
109
|
+
F.avg("count").alias("avg_rows"),
|
|
110
|
+
F.stddev("count").alias("stddev")
|
|
111
|
+
)
|
|
112
|
+
stats.show()
|
|
113
|
+
|
|
114
|
+
# Identify skew: max/avg ratio > 3 indicates skew
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
---
|
|
118
|
+
|
|
119
|
+
## Shuffle Partitions
|
|
120
|
+
|
|
121
|
+
### Configuration
|
|
122
|
+
|
|
123
|
+
```python
|
|
124
|
+
# Default shuffle partitions (200) - often suboptimal
|
|
125
|
+
spark.conf.set("spark.sql.shuffle.partitions", 200)
|
|
126
|
+
|
|
127
|
+
# For small data (<10GB), reduce
|
|
128
|
+
spark.conf.set("spark.sql.shuffle.partitions", 50)
|
|
129
|
+
|
|
130
|
+
# For large data (>100GB), increase
|
|
131
|
+
spark.conf.set("spark.sql.shuffle.partitions", 2000)
|
|
132
|
+
|
|
133
|
+
# Adaptive Query Execution (Spark 3.0+) - dynamic partition sizing
|
|
134
|
+
spark.conf.set("spark.sql.adaptive.enabled", "true")
|
|
135
|
+
spark.conf.set("spark.sql.adaptive.coalescePartitions.enabled", "true")
|
|
136
|
+
spark.conf.set("spark.sql.adaptive.coalescePartitions.minPartitionSize", "64MB")
|
|
137
|
+
spark.conf.set("spark.sql.adaptive.advisoryPartitionSizeInBytes", "128MB")
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
### AQE Automatic Optimization (Spark 3.x)
|
|
141
|
+
|
|
142
|
+
```python
|
|
143
|
+
# Enable full AQE suite
|
|
144
|
+
spark.conf.set("spark.sql.adaptive.enabled", "true")
|
|
145
|
+
|
|
146
|
+
# Auto-coalesce shuffle partitions
|
|
147
|
+
spark.conf.set("spark.sql.adaptive.coalescePartitions.enabled", "true")
|
|
148
|
+
spark.conf.set("spark.sql.adaptive.coalescePartitions.parallelismFirst", "false")
|
|
149
|
+
|
|
150
|
+
# Handle skewed partitions automatically
|
|
151
|
+
spark.conf.set("spark.sql.adaptive.skewJoin.enabled", "true")
|
|
152
|
+
spark.conf.set("spark.sql.adaptive.skewJoin.skewedPartitionFactor", 5)
|
|
153
|
+
spark.conf.set("spark.sql.adaptive.skewJoin.skewedPartitionThresholdInBytes", "256MB")
|
|
154
|
+
|
|
155
|
+
# Local shuffle reader (avoid remote reads when possible)
|
|
156
|
+
spark.conf.set("spark.sql.adaptive.localShuffleReader.enabled", "true")
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
**Spark UI Check:** With AQE, check "Adaptive" badge in SQL tab. View coalesced partition counts in stage details.
|
|
160
|
+
|
|
161
|
+
---
|
|
162
|
+
|
|
163
|
+
## Caching and Persistence
|
|
164
|
+
|
|
165
|
+
### When to Cache
|
|
166
|
+
|
|
167
|
+
**Cache when:**
|
|
168
|
+
- DataFrame is reused multiple times in same job
|
|
169
|
+
- DataFrame is expensive to compute (complex joins/aggregations)
|
|
170
|
+
- Iterative algorithms (ML training loops)
|
|
171
|
+
- Interactive exploration in notebooks
|
|
172
|
+
|
|
173
|
+
**Do NOT cache when:**
|
|
174
|
+
- DataFrame used only once
|
|
175
|
+
- Data doesn't fit in cluster memory
|
|
176
|
+
- Source data is already fast (local SSD, columnar formats)
|
|
177
|
+
- Storage level causes excessive GC
|
|
178
|
+
|
|
179
|
+
### Persistence Levels
|
|
180
|
+
|
|
181
|
+
```python
|
|
182
|
+
from pyspark import StorageLevel
|
|
183
|
+
|
|
184
|
+
# Memory only (default for cache())
|
|
185
|
+
df.cache() # Equivalent to persist(MEMORY_AND_DISK)
|
|
186
|
+
df.persist() # Same as cache()
|
|
187
|
+
|
|
188
|
+
# Specific storage levels
|
|
189
|
+
df.persist(StorageLevel.MEMORY_ONLY) # Fast, may lose partitions
|
|
190
|
+
df.persist(StorageLevel.MEMORY_AND_DISK) # Spill to disk if needed
|
|
191
|
+
df.persist(StorageLevel.MEMORY_ONLY_SER) # Serialized, less memory, slower
|
|
192
|
+
df.persist(StorageLevel.MEMORY_AND_DISK_SER) # Serialized with disk spill
|
|
193
|
+
df.persist(StorageLevel.DISK_ONLY) # Only disk, slowest
|
|
194
|
+
df.persist(StorageLevel.OFF_HEAP) # Off-heap memory
|
|
195
|
+
|
|
196
|
+
# With replication (for fault tolerance)
|
|
197
|
+
df.persist(StorageLevel.MEMORY_AND_DISK_2) # 2x replication
|
|
198
|
+
|
|
199
|
+
# Unpersist when done
|
|
200
|
+
df.unpersist()
|
|
201
|
+
df.unpersist(blocking=True) # Wait for completion
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
```scala
|
|
205
|
+
// Scala persistence
|
|
206
|
+
import org.apache.spark.storage.StorageLevel
|
|
207
|
+
|
|
208
|
+
df.cache()
|
|
209
|
+
df.persist(StorageLevel.MEMORY_AND_DISK_SER)
|
|
210
|
+
df.unpersist()
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
### Storage Level Selection Guide
|
|
214
|
+
|
|
215
|
+
| Storage Level | Use When |
|
|
216
|
+
|---------------|----------|
|
|
217
|
+
| MEMORY_ONLY | Enough memory, need fastest access |
|
|
218
|
+
| MEMORY_AND_DISK | Default, safe for most cases |
|
|
219
|
+
| MEMORY_ONLY_SER | Memory constrained, CPU available |
|
|
220
|
+
| MEMORY_AND_DISK_SER | Large data, memory constrained |
|
|
221
|
+
| DISK_ONLY | Very large data, memory scarce |
|
|
222
|
+
| OFF_HEAP | Using Tungsten off-heap memory |
|
|
223
|
+
|
|
224
|
+
### Caching Best Practices
|
|
225
|
+
|
|
226
|
+
```python
|
|
227
|
+
# Pattern 1: Cache after expensive transformation
|
|
228
|
+
expensive_df = source_df \
|
|
229
|
+
.join(lookup_df, "key") \
|
|
230
|
+
.groupBy("category").agg(F.sum("amount"))
|
|
231
|
+
|
|
232
|
+
expensive_df.cache()
|
|
233
|
+
|
|
234
|
+
# Trigger caching with action
|
|
235
|
+
expensive_df.count()
|
|
236
|
+
|
|
237
|
+
# Reuse cached data
|
|
238
|
+
result1 = expensive_df.filter(F.col("category") == "A")
|
|
239
|
+
result2 = expensive_df.filter(F.col("category") == "B")
|
|
240
|
+
|
|
241
|
+
# Clean up
|
|
242
|
+
expensive_df.unpersist()
|
|
243
|
+
|
|
244
|
+
# Pattern 2: Cache at checkpoint in iterative algorithm
|
|
245
|
+
for iteration in range(100):
|
|
246
|
+
df = df.transform(update_function)
|
|
247
|
+
if iteration % 10 == 0:
|
|
248
|
+
df.cache()
|
|
249
|
+
df.count() # Materialize
|
|
250
|
+
df.unpersist() # Clean previous
|
|
251
|
+
|
|
252
|
+
# Pattern 3: Checkpoint to break lineage (long pipelines)
|
|
253
|
+
spark.sparkContext.setCheckpointDir("hdfs://path/checkpoints/")
|
|
254
|
+
df.checkpoint() # Truncates lineage, saves to reliable storage
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
### Monitoring Cache Usage
|
|
258
|
+
|
|
259
|
+
```python
|
|
260
|
+
# Check if DataFrame is cached
|
|
261
|
+
print(df.storageLevel) # StorageLevel(False, False, False, False, 1) = not cached
|
|
262
|
+
|
|
263
|
+
# Check storage tab in Spark UI for:
|
|
264
|
+
# - Size in Memory
|
|
265
|
+
# - Size on Disk
|
|
266
|
+
# - Fraction Cached (should be 100%)
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
**Spark UI Check:** Storage tab shows cached RDDs/DataFrames. Monitor "Fraction Cached" - if < 100%, memory is insufficient.
|
|
270
|
+
|
|
271
|
+
---
|
|
272
|
+
|
|
273
|
+
## Broadcast Variables
|
|
274
|
+
|
|
275
|
+
### When to Use Broadcast
|
|
276
|
+
|
|
277
|
+
- Small lookup tables (< 200MB)
|
|
278
|
+
- Dimension tables joined to large fact tables
|
|
279
|
+
- Configuration data used across all tasks
|
|
280
|
+
- Avoiding shuffle in map-side joins
|
|
281
|
+
|
|
282
|
+
### DataFrame Broadcast Join
|
|
283
|
+
|
|
284
|
+
```python
|
|
285
|
+
from pyspark.sql.functions import broadcast
|
|
286
|
+
|
|
287
|
+
# Explicit broadcast hint
|
|
288
|
+
large_df = spark.read.parquet("s3://bucket/transactions/") # 100GB
|
|
289
|
+
small_df = spark.read.parquet("s3://bucket/categories/") # 50MB
|
|
290
|
+
|
|
291
|
+
# Broadcast small table for efficient join
|
|
292
|
+
result = large_df.join(broadcast(small_df), "category_id")
|
|
293
|
+
|
|
294
|
+
# Auto-broadcast threshold configuration
|
|
295
|
+
spark.conf.set("spark.sql.autoBroadcastJoinThreshold", 100 * 1024 * 1024) # 100MB
|
|
296
|
+
|
|
297
|
+
# Disable auto-broadcast (force sort-merge join)
|
|
298
|
+
spark.conf.set("spark.sql.autoBroadcastJoinThreshold", -1)
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
### RDD Broadcast Variables
|
|
302
|
+
|
|
303
|
+
```python
|
|
304
|
+
# Create broadcast variable
|
|
305
|
+
lookup_dict = {"A": 1, "B": 2, "C": 3}
|
|
306
|
+
broadcast_lookup = spark.sparkContext.broadcast(lookup_dict)
|
|
307
|
+
|
|
308
|
+
# Use in transformation
|
|
309
|
+
def enrich_with_lookup(row):
|
|
310
|
+
lookup = broadcast_lookup.value
|
|
311
|
+
return Row(
|
|
312
|
+
id=row.id,
|
|
313
|
+
code=row.code,
|
|
314
|
+
value=lookup.get(row.code, 0)
|
|
315
|
+
)
|
|
316
|
+
|
|
317
|
+
enriched_rdd = df.rdd.map(enrich_with_lookup)
|
|
318
|
+
|
|
319
|
+
# Clean up
|
|
320
|
+
broadcast_lookup.unpersist()
|
|
321
|
+
broadcast_lookup.destroy()
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
### Broadcast Size Limits
|
|
325
|
+
|
|
326
|
+
```python
|
|
327
|
+
# Maximum broadcast size (default 8GB, adjustable)
|
|
328
|
+
spark.conf.set("spark.sql.autoBroadcastJoinThreshold", 200 * 1024 * 1024) # 200MB
|
|
329
|
+
|
|
330
|
+
# For larger broadcasts
|
|
331
|
+
spark.conf.set("spark.driver.maxResultSize", "4g")
|
|
332
|
+
|
|
333
|
+
# Monitor broadcast time in Spark UI
|
|
334
|
+
# Long broadcast time indicates table too large
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
**Warning:** Broadcasting tables > 200MB can cause driver OOM and slow broadcast. Use sort-merge join instead.
|
|
338
|
+
|
|
339
|
+
---
|
|
340
|
+
|
|
341
|
+
## Partitioning Strategies for Common Patterns
|
|
342
|
+
|
|
343
|
+
### Time-Series Data
|
|
344
|
+
|
|
345
|
+
```python
|
|
346
|
+
# Partition by date for time-range queries
|
|
347
|
+
df_partitioned = df.repartition("date")
|
|
348
|
+
|
|
349
|
+
# Range partition for ordered access
|
|
350
|
+
df_range = df.repartitionByRange(365, "date") # One year
|
|
351
|
+
|
|
352
|
+
# Write partitioned by date
|
|
353
|
+
df.write.partitionBy("year", "month", "day").parquet("s3://bucket/data/")
|
|
354
|
+
|
|
355
|
+
# Read with partition pruning
|
|
356
|
+
df = spark.read.parquet("s3://bucket/data/") \
|
|
357
|
+
.filter(F.col("year") == 2024) # Only reads 2024 partitions
|
|
358
|
+
```
|
|
359
|
+
|
|
360
|
+
### User/Entity Data
|
|
361
|
+
|
|
362
|
+
```python
|
|
363
|
+
# Partition by user_id for user-specific queries
|
|
364
|
+
df_user_partitioned = df.repartition(1000, "user_id")
|
|
365
|
+
|
|
366
|
+
# Co-partition for efficient joins
|
|
367
|
+
users_partitioned = users.repartition(1000, "user_id")
|
|
368
|
+
orders_partitioned = orders.repartition(1000, "user_id")
|
|
369
|
+
|
|
370
|
+
# Join without shuffle (if partitioners match)
|
|
371
|
+
joined = users_partitioned.join(orders_partitioned, "user_id")
|
|
372
|
+
```
|
|
373
|
+
|
|
374
|
+
### Skewed Data
|
|
375
|
+
|
|
376
|
+
```python
|
|
377
|
+
# Salt skewed keys
|
|
378
|
+
salt_buckets = 10
|
|
379
|
+
|
|
380
|
+
# Add salt to skewed table
|
|
381
|
+
salted_df = large_df.withColumn(
|
|
382
|
+
"salted_key",
|
|
383
|
+
F.concat(
|
|
384
|
+
F.col("join_key"),
|
|
385
|
+
F.lit("_"),
|
|
386
|
+
(F.monotonically_increasing_id() % salt_buckets).cast("string")
|
|
387
|
+
)
|
|
388
|
+
)
|
|
389
|
+
|
|
390
|
+
# Explode small table to match
|
|
391
|
+
from pyspark.sql.functions import explode, array, lit
|
|
392
|
+
|
|
393
|
+
small_exploded = small_df.withColumn(
|
|
394
|
+
"salt",
|
|
395
|
+
explode(array([lit(i) for i in range(salt_buckets)]))
|
|
396
|
+
).withColumn(
|
|
397
|
+
"salted_key",
|
|
398
|
+
F.concat(F.col("join_key"), F.lit("_"), F.col("salt").cast("string"))
|
|
399
|
+
)
|
|
400
|
+
|
|
401
|
+
# Join on salted key
|
|
402
|
+
result = salted_df.join(small_exploded, "salted_key")
|
|
403
|
+
```
|
|
404
|
+
|
|
405
|
+
---
|
|
406
|
+
|
|
407
|
+
## File Partitioning (Write Optimization)
|
|
408
|
+
|
|
409
|
+
### Hive-Style Partitioning
|
|
410
|
+
|
|
411
|
+
```python
|
|
412
|
+
# Write with partitioning
|
|
413
|
+
df.write \
|
|
414
|
+
.mode("overwrite") \
|
|
415
|
+
.partitionBy("year", "month") \
|
|
416
|
+
.parquet("s3://bucket/data/")
|
|
417
|
+
|
|
418
|
+
# Result directory structure:
|
|
419
|
+
# s3://bucket/data/year=2024/month=01/part-*.parquet
|
|
420
|
+
# s3://bucket/data/year=2024/month=02/part-*.parquet
|
|
421
|
+
|
|
422
|
+
# Read with partition discovery
|
|
423
|
+
df = spark.read.parquet("s3://bucket/data/")
|
|
424
|
+
# Columns year, month automatically added from path
|
|
425
|
+
```
|
|
426
|
+
|
|
427
|
+
### Bucketing (Hash-Based File Partitioning)
|
|
428
|
+
|
|
429
|
+
```python
|
|
430
|
+
# Write bucketed table for optimized joins
|
|
431
|
+
df.write \
|
|
432
|
+
.mode("overwrite") \
|
|
433
|
+
.bucketBy(100, "user_id") \
|
|
434
|
+
.sortBy("timestamp") \
|
|
435
|
+
.saveAsTable("bucketed_orders")
|
|
436
|
+
|
|
437
|
+
# Read bucketed table
|
|
438
|
+
orders = spark.table("bucketed_orders")
|
|
439
|
+
users = spark.table("bucketed_users") # Same bucket count
|
|
440
|
+
|
|
441
|
+
# Bucket join - no shuffle if buckets match
|
|
442
|
+
result = orders.join(users, "user_id")
|
|
443
|
+
```
|
|
444
|
+
|
|
445
|
+
**Note:** Bucketing requires Hive metastore and saveAsTable. Doesn't work with direct file writes.
|
|
446
|
+
|
|
447
|
+
### Controlling Output Files
|
|
448
|
+
|
|
449
|
+
```python
|
|
450
|
+
# Control number of output files
|
|
451
|
+
# One file per partition
|
|
452
|
+
df.coalesce(1).write.parquet("s3://bucket/output/")
|
|
453
|
+
|
|
454
|
+
# Multiple files per partition (for large partitions)
|
|
455
|
+
df.repartition(100).write.parquet("s3://bucket/output/")
|
|
456
|
+
|
|
457
|
+
# Max records per file
|
|
458
|
+
df.write \
|
|
459
|
+
.option("maxRecordsPerFile", 1000000) \
|
|
460
|
+
.parquet("s3://bucket/output/")
|
|
461
|
+
```
|
|
462
|
+
|
|
463
|
+
---
|
|
464
|
+
|
|
465
|
+
## Spark UI Analysis for Partitioning/Caching
|
|
466
|
+
|
|
467
|
+
### Jobs Tab
|
|
468
|
+
|
|
469
|
+
- Check if cached data shows "(cached)" in DAG
|
|
470
|
+
- Look for skipped stages (using cached data)
|
|
471
|
+
|
|
472
|
+
### Stages Tab
|
|
473
|
+
|
|
474
|
+
- **Shuffle Write Size**: Large values indicate repartition opportunities
|
|
475
|
+
- **Shuffle Read Size**: Should be similar across tasks (no skew)
|
|
476
|
+
- **Task Duration Distribution**: Wide variance indicates partition imbalance
|
|
477
|
+
|
|
478
|
+
### Storage Tab
|
|
479
|
+
|
|
480
|
+
- **Size in Memory**: Actual cached size
|
|
481
|
+
- **Size on Disk**: Spilled size
|
|
482
|
+
- **Fraction Cached**: Should be 100% if memory sufficient
|
|
483
|
+
|
|
484
|
+
### SQL Tab
|
|
485
|
+
|
|
486
|
+
- Look for "BroadcastExchange" - indicates broadcast join
|
|
487
|
+
- Look for "ShuffleExchange" - indicates data movement
|
|
488
|
+
- Check "Rows Output" at each stage for data flow
|
|
489
|
+
|
|
490
|
+
---
|
|
491
|
+
|
|
492
|
+
## Common Anti-Patterns
|
|
493
|
+
|
|
494
|
+
```python
|
|
495
|
+
# BAD: Caching without measuring benefit
|
|
496
|
+
for table in all_tables:
|
|
497
|
+
spark.read.parquet(table).cache() # Wastes memory
|
|
498
|
+
|
|
499
|
+
# GOOD: Cache only if reused
|
|
500
|
+
expensive_df.cache()
|
|
501
|
+
result1 = expensive_df.groupBy("a").count()
|
|
502
|
+
result2 = expensive_df.groupBy("b").count()
|
|
503
|
+
expensive_df.unpersist()
|
|
504
|
+
|
|
505
|
+
# BAD: Too many small partitions
|
|
506
|
+
df.repartition(10000) # Creates scheduling overhead
|
|
507
|
+
|
|
508
|
+
# GOOD: Right-size partitions (128MB-256MB each)
|
|
509
|
+
df.repartition(100)
|
|
510
|
+
|
|
511
|
+
# BAD: Too few partitions for large data
|
|
512
|
+
df.coalesce(1) # Single partition can't parallelize
|
|
513
|
+
|
|
514
|
+
# GOOD: Maintain parallelism
|
|
515
|
+
df.coalesce(max(1, target_size))
|
|
516
|
+
|
|
517
|
+
# BAD: Repartition before filter
|
|
518
|
+
df.repartition(1000).filter(F.col("active") == True) # Shuffles then filters
|
|
519
|
+
|
|
520
|
+
# GOOD: Filter then coalesce
|
|
521
|
+
df.filter(F.col("active") == True).coalesce(100) # Filter first, then resize
|
|
522
|
+
|
|
523
|
+
# BAD: Broadcasting large table
|
|
524
|
+
result = large.join(broadcast(also_large), "key") # OOM risk
|
|
525
|
+
|
|
526
|
+
# GOOD: Let Spark decide or use sort-merge
|
|
527
|
+
result = large.join(also_large, "key") # Sort-merge join
|
|
528
|
+
```
|
|
529
|
+
|
|
530
|
+
---
|
|
531
|
+
|
|
532
|
+
## Best Practices Summary
|
|
533
|
+
|
|
534
|
+
1. **Target 128-256MB partitions** - Not too small (overhead) or large (OOM)
|
|
535
|
+
2. **Use 2-4 partitions per core** - Maximize parallelism
|
|
536
|
+
3. **Enable AQE in Spark 3.x** - Automatic partition optimization
|
|
537
|
+
4. **Cache only reused DataFrames** - Measure before caching everything
|
|
538
|
+
5. **Use MEMORY_AND_DISK** - Safe default storage level
|
|
539
|
+
6. **Broadcast tables < 200MB** - Avoid shuffle for small dimension tables
|
|
540
|
+
7. **Coalesce after filters** - Reduce partitions when data shrinks
|
|
541
|
+
8. **Repartition for joins** - Co-partition related tables
|
|
542
|
+
9. **Partition writes by filter columns** - Enable partition pruning
|
|
543
|
+
10. **Monitor Storage tab** - Ensure cache fits in memory
|