dojo.md 0.2.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/courses/GENERATION_LOG.md +45 -0
- package/courses/aws-lambda-debugging/course.yaml +11 -0
- package/courses/aws-lambda-debugging/scenarios/level-1/api-gateway-integration.yaml +71 -0
- package/courses/aws-lambda-debugging/scenarios/level-1/cloudwatch-logs-basics.yaml +64 -0
- package/courses/aws-lambda-debugging/scenarios/level-1/cold-start-basics.yaml +70 -0
- package/courses/aws-lambda-debugging/scenarios/level-1/environment-variable-issues.yaml +72 -0
- package/courses/aws-lambda-debugging/scenarios/level-1/first-debugging-shift.yaml +73 -0
- package/courses/aws-lambda-debugging/scenarios/level-1/handler-import-errors.yaml +71 -0
- package/courses/aws-lambda-debugging/scenarios/level-1/iam-permission-errors.yaml +68 -0
- package/courses/aws-lambda-debugging/scenarios/level-1/invocation-errors.yaml +72 -0
- package/courses/aws-lambda-debugging/scenarios/level-1/lambda-timeout-errors.yaml +65 -0
- package/courses/aws-lambda-debugging/scenarios/level-1/memory-and-oom.yaml +70 -0
- package/courses/aws-lambda-debugging/scenarios/level-2/async-invocation-failures.yaml +72 -0
- package/courses/aws-lambda-debugging/scenarios/level-2/cold-start-optimization.yaml +76 -0
- package/courses/aws-lambda-debugging/scenarios/level-2/dynamodb-streams-debugging.yaml +70 -0
- package/courses/aws-lambda-debugging/scenarios/level-2/intermediate-debugging-shift.yaml +71 -0
- package/courses/aws-lambda-debugging/scenarios/level-2/lambda-concurrency-management.yaml +70 -0
- package/courses/aws-lambda-debugging/scenarios/level-2/lambda-layers-debugging.yaml +76 -0
- package/courses/aws-lambda-debugging/scenarios/level-2/sam-local-debugging.yaml +74 -0
- package/courses/aws-lambda-debugging/scenarios/level-2/sqs-event-source.yaml +72 -0
- package/courses/aws-lambda-debugging/scenarios/level-2/vpc-networking-issues.yaml +71 -0
- package/courses/aws-lambda-debugging/scenarios/level-2/xray-tracing.yaml +62 -0
- package/courses/aws-lambda-debugging/scenarios/level-3/advanced-debugging-shift.yaml +72 -0
- package/courses/aws-lambda-debugging/scenarios/level-3/container-image-lambda.yaml +79 -0
- package/courses/aws-lambda-debugging/scenarios/level-3/cross-account-invocation.yaml +72 -0
- package/courses/aws-lambda-debugging/scenarios/level-3/eventbridge-patterns.yaml +79 -0
- package/courses/aws-lambda-debugging/scenarios/level-3/iac-deployment-debugging.yaml +68 -0
- package/courses/aws-lambda-debugging/scenarios/level-3/kinesis-stream-processing.yaml +64 -0
- package/courses/aws-lambda-debugging/scenarios/level-3/lambda-at-edge.yaml +64 -0
- package/courses/aws-lambda-debugging/scenarios/level-3/lambda-extensions-debugging.yaml +67 -0
- package/courses/aws-lambda-debugging/scenarios/level-3/powertools-observability.yaml +79 -0
- package/courses/aws-lambda-debugging/scenarios/level-3/step-functions-debugging.yaml +80 -0
- package/courses/aws-lambda-debugging/scenarios/level-4/cost-optimization-strategy.yaml +67 -0
- package/courses/aws-lambda-debugging/scenarios/level-4/expert-debugging-shift.yaml +62 -0
- package/courses/aws-lambda-debugging/scenarios/level-4/incident-management-serverless.yaml +61 -0
- package/courses/aws-lambda-debugging/scenarios/level-4/multi-region-serverless.yaml +67 -0
- package/courses/aws-lambda-debugging/scenarios/level-4/observability-platform-design.yaml +71 -0
- package/courses/aws-lambda-debugging/scenarios/level-4/serverless-architecture-design.yaml +64 -0
- package/courses/aws-lambda-debugging/scenarios/level-4/serverless-data-architecture.yaml +66 -0
- package/courses/aws-lambda-debugging/scenarios/level-4/serverless-migration-strategy.yaml +65 -0
- package/courses/aws-lambda-debugging/scenarios/level-4/serverless-security-design.yaml +60 -0
- package/courses/aws-lambda-debugging/scenarios/level-4/serverless-testing-strategy.yaml +62 -0
- package/courses/aws-lambda-debugging/scenarios/level-5/board-serverless-strategy.yaml +63 -0
- package/courses/aws-lambda-debugging/scenarios/level-5/consulting-serverless-adoption.yaml +57 -0
- package/courses/aws-lambda-debugging/scenarios/level-5/industry-serverless-patterns.yaml +62 -0
- package/courses/aws-lambda-debugging/scenarios/level-5/ma-serverless-integration.yaml +75 -0
- package/courses/aws-lambda-debugging/scenarios/level-5/master-debugging-shift.yaml +61 -0
- package/courses/aws-lambda-debugging/scenarios/level-5/organizational-serverless-transformation.yaml +65 -0
- package/courses/aws-lambda-debugging/scenarios/level-5/regulatory-serverless.yaml +61 -0
- package/courses/aws-lambda-debugging/scenarios/level-5/serverless-economics.yaml +65 -0
- package/courses/aws-lambda-debugging/scenarios/level-5/serverless-future-technology.yaml +66 -0
- package/courses/aws-lambda-debugging/scenarios/level-5/serverless-platform-design.yaml +71 -0
- package/courses/docker-container-debugging/course.yaml +11 -0
- package/courses/docker-container-debugging/scenarios/level-1/container-exit-codes.yaml +59 -0
- package/courses/docker-container-debugging/scenarios/level-1/container-networking-basics.yaml +69 -0
- package/courses/docker-container-debugging/scenarios/level-1/docker-logs-debugging.yaml +67 -0
- package/courses/docker-container-debugging/scenarios/level-1/dockerfile-build-failures.yaml +71 -0
- package/courses/docker-container-debugging/scenarios/level-1/environment-variable-issues.yaml +74 -0
- package/courses/docker-container-debugging/scenarios/level-1/first-debugging-shift.yaml +70 -0
- package/courses/docker-container-debugging/scenarios/level-1/image-pull-failures.yaml +68 -0
- package/courses/docker-container-debugging/scenarios/level-1/port-mapping-issues.yaml +67 -0
- package/courses/docker-container-debugging/scenarios/level-1/resource-limits-oom.yaml +70 -0
- package/courses/docker-container-debugging/scenarios/level-1/volume-mount-problems.yaml +66 -0
- package/courses/docker-container-debugging/scenarios/level-2/container-health-checks.yaml +73 -0
- package/courses/docker-container-debugging/scenarios/level-2/docker-compose-debugging.yaml +66 -0
- package/courses/docker-container-debugging/scenarios/level-2/docker-exec-debugging.yaml +71 -0
- package/courses/docker-container-debugging/scenarios/level-2/image-layer-optimization.yaml +81 -0
- package/courses/docker-container-debugging/scenarios/level-2/intermediate-debugging-shift.yaml +73 -0
- package/courses/docker-container-debugging/scenarios/level-2/logging-and-log-rotation.yaml +76 -0
- package/courses/docker-container-debugging/scenarios/level-2/multi-stage-build-debugging.yaml +76 -0
- package/courses/docker-container-debugging/scenarios/level-2/network-debugging-tools.yaml +67 -0
- package/courses/docker-container-debugging/scenarios/level-2/pid1-signal-handling.yaml +71 -0
- package/courses/docker-container-debugging/scenarios/level-2/security-scanning-basics.yaml +67 -0
- package/courses/docker-container-debugging/scenarios/level-3/advanced-debugging-shift.yaml +77 -0
- package/courses/docker-container-debugging/scenarios/level-3/buildkit-optimization.yaml +67 -0
- package/courses/docker-container-debugging/scenarios/level-3/container-filesystem-debugging.yaml +70 -0
- package/courses/docker-container-debugging/scenarios/level-3/container-security-hardening.yaml +74 -0
- package/courses/docker-container-debugging/scenarios/level-3/disk-space-management.yaml +74 -0
- package/courses/docker-container-debugging/scenarios/level-3/docker-api-automation.yaml +72 -0
- package/courses/docker-container-debugging/scenarios/level-3/docker-daemon-issues.yaml +73 -0
- package/courses/docker-container-debugging/scenarios/level-3/docker-in-docker-ci.yaml +69 -0
- package/courses/docker-container-debugging/scenarios/level-3/overlay-network-debugging.yaml +70 -0
- package/courses/docker-container-debugging/scenarios/level-3/production-container-ops.yaml +71 -0
- package/courses/docker-container-debugging/scenarios/level-4/cicd-pipeline-design.yaml +66 -0
- package/courses/docker-container-debugging/scenarios/level-4/container-monitoring-observability.yaml +63 -0
- package/courses/docker-container-debugging/scenarios/level-4/container-orchestration-strategy.yaml +62 -0
- package/courses/docker-container-debugging/scenarios/level-4/container-performance-engineering.yaml +64 -0
- package/courses/docker-container-debugging/scenarios/level-4/container-security-architecture.yaml +66 -0
- package/courses/docker-container-debugging/scenarios/level-4/enterprise-image-management.yaml +58 -0
- package/courses/docker-container-debugging/scenarios/level-4/expert-debugging-shift.yaml +63 -0
- package/courses/docker-container-debugging/scenarios/level-4/incident-response-containers.yaml +70 -0
- package/courses/docker-container-debugging/scenarios/level-4/multi-environment-management.yaml +65 -0
- package/courses/docker-container-debugging/scenarios/level-4/stateful-service-containers.yaml +65 -0
- package/courses/docker-container-debugging/scenarios/level-5/board-infrastructure-strategy.yaml +58 -0
- package/courses/docker-container-debugging/scenarios/level-5/consulting-container-strategy.yaml +61 -0
- package/courses/docker-container-debugging/scenarios/level-5/container-platform-architecture.yaml +67 -0
- package/courses/docker-container-debugging/scenarios/level-5/container-platform-economics.yaml +67 -0
- package/courses/docker-container-debugging/scenarios/level-5/container-technology-evolution.yaml +67 -0
- package/courses/docker-container-debugging/scenarios/level-5/disaster-recovery-containers.yaml +66 -0
- package/courses/docker-container-debugging/scenarios/level-5/industry-container-patterns.yaml +71 -0
- package/courses/docker-container-debugging/scenarios/level-5/master-debugging-shift.yaml +62 -0
- package/courses/docker-container-debugging/scenarios/level-5/organizational-transformation.yaml +67 -0
- package/courses/docker-container-debugging/scenarios/level-5/regulatory-compliance-containers.yaml +61 -0
- package/courses/kubernetes-deployment-troubleshooting/course.yaml +12 -0
- package/courses/kubernetes-deployment-troubleshooting/scenarios/level-1/configmap-secret-issues.yaml +69 -0
- package/courses/kubernetes-deployment-troubleshooting/scenarios/level-1/crashloopbackoff.yaml +68 -0
- package/courses/kubernetes-deployment-troubleshooting/scenarios/level-1/deployment-rollout.yaml +56 -0
- package/courses/kubernetes-deployment-troubleshooting/scenarios/level-1/first-troubleshooting-shift.yaml +65 -0
- package/courses/kubernetes-deployment-troubleshooting/scenarios/level-1/health-probe-failures.yaml +70 -0
- package/courses/kubernetes-deployment-troubleshooting/scenarios/level-1/imagepullbackoff.yaml +57 -0
- package/courses/kubernetes-deployment-troubleshooting/scenarios/level-1/kubectl-debugging-basics.yaml +56 -0
- package/courses/kubernetes-deployment-troubleshooting/scenarios/level-1/oomkilled.yaml +70 -0
- package/courses/kubernetes-deployment-troubleshooting/scenarios/level-1/pending-pods.yaml +68 -0
- package/courses/kubernetes-deployment-troubleshooting/scenarios/level-1/service-not-reachable.yaml +66 -0
- package/courses/kubernetes-deployment-troubleshooting/scenarios/level-2/dns-resolution-failures.yaml +63 -0
- package/courses/kubernetes-deployment-troubleshooting/scenarios/level-2/helm-deployment-failures.yaml +63 -0
- package/courses/kubernetes-deployment-troubleshooting/scenarios/level-2/hpa-scaling-issues.yaml +62 -0
- package/courses/kubernetes-deployment-troubleshooting/scenarios/level-2/ingress-routing-issues.yaml +63 -0
- package/courses/kubernetes-deployment-troubleshooting/scenarios/level-2/init-container-failures.yaml +63 -0
- package/courses/kubernetes-deployment-troubleshooting/scenarios/level-2/intermediate-troubleshooting-shift.yaml +66 -0
- package/courses/kubernetes-deployment-troubleshooting/scenarios/level-2/network-policy-blocking.yaml +67 -0
- package/courses/kubernetes-deployment-troubleshooting/scenarios/level-2/persistent-volume-issues.yaml +69 -0
- package/courses/kubernetes-deployment-troubleshooting/scenarios/level-2/rbac-permission-denied.yaml +57 -0
- package/courses/kubernetes-deployment-troubleshooting/scenarios/level-2/resource-quota-limits.yaml +64 -0
- package/courses/kubernetes-deployment-troubleshooting/scenarios/level-3/advanced-troubleshooting-shift.yaml +69 -0
- package/courses/kubernetes-deployment-troubleshooting/scenarios/level-3/cluster-upgrade-failures.yaml +71 -0
- package/courses/kubernetes-deployment-troubleshooting/scenarios/level-3/gitops-drift-detection.yaml +62 -0
- package/courses/kubernetes-deployment-troubleshooting/scenarios/level-3/job-cronjob-failures.yaml +67 -0
- package/courses/kubernetes-deployment-troubleshooting/scenarios/level-3/monitoring-alerting-gaps.yaml +64 -0
- package/courses/kubernetes-deployment-troubleshooting/scenarios/level-3/multi-container-debugging.yaml +68 -0
- package/courses/kubernetes-deployment-troubleshooting/scenarios/level-3/node-pressure-evictions.yaml +70 -0
- package/courses/kubernetes-deployment-troubleshooting/scenarios/level-3/pod-disruption-budgets.yaml +59 -0
- package/courses/kubernetes-deployment-troubleshooting/scenarios/level-3/service-mesh-debugging.yaml +64 -0
- package/courses/kubernetes-deployment-troubleshooting/scenarios/level-3/statefulset-troubleshooting.yaml +69 -0
- package/courses/kubernetes-deployment-troubleshooting/scenarios/level-4/capacity-planning.yaml +65 -0
- package/courses/kubernetes-deployment-troubleshooting/scenarios/level-4/cost-optimization.yaml +57 -0
- package/courses/kubernetes-deployment-troubleshooting/scenarios/level-4/disaster-recovery-design.yaml +56 -0
- package/courses/kubernetes-deployment-troubleshooting/scenarios/level-4/executive-communication.yaml +62 -0
- package/courses/kubernetes-deployment-troubleshooting/scenarios/level-4/expert-troubleshooting-shift.yaml +65 -0
- package/courses/kubernetes-deployment-troubleshooting/scenarios/level-4/incident-management-process.yaml +59 -0
- package/courses/kubernetes-deployment-troubleshooting/scenarios/level-4/multi-cluster-operations.yaml +62 -0
- package/courses/kubernetes-deployment-troubleshooting/scenarios/level-4/multi-tenancy-design.yaml +55 -0
- package/courses/kubernetes-deployment-troubleshooting/scenarios/level-4/platform-engineering.yaml +59 -0
- package/courses/kubernetes-deployment-troubleshooting/scenarios/level-4/security-hardening.yaml +58 -0
- package/courses/kubernetes-deployment-troubleshooting/scenarios/level-5/behavioral-science.yaml +62 -0
- package/courses/kubernetes-deployment-troubleshooting/scenarios/level-5/board-strategy.yaml +61 -0
- package/courses/kubernetes-deployment-troubleshooting/scenarios/level-5/cloud-native-future.yaml +65 -0
- package/courses/kubernetes-deployment-troubleshooting/scenarios/level-5/comprehensive-platform.yaml +57 -0
- package/courses/kubernetes-deployment-troubleshooting/scenarios/level-5/consulting-engagement.yaml +62 -0
- package/courses/kubernetes-deployment-troubleshooting/scenarios/level-5/industry-benchmarks.yaml +58 -0
- package/courses/kubernetes-deployment-troubleshooting/scenarios/level-5/ma-integration.yaml +62 -0
- package/courses/kubernetes-deployment-troubleshooting/scenarios/level-5/master-troubleshooting-shift.yaml +73 -0
- package/courses/kubernetes-deployment-troubleshooting/scenarios/level-5/product-development.yaml +65 -0
- package/courses/kubernetes-deployment-troubleshooting/scenarios/level-5/regulatory-compliance.yaml +76 -0
- package/courses/mysql-query-optimization/course.yaml +11 -0
- package/courses/mysql-query-optimization/scenarios/level-1/buffer-pool-basics.yaml +65 -0
- package/courses/mysql-query-optimization/scenarios/level-1/explain-basics.yaml +66 -0
- package/courses/mysql-query-optimization/scenarios/level-1/first-optimization-shift.yaml +78 -0
- package/courses/mysql-query-optimization/scenarios/level-1/innodb-index-fundamentals.yaml +68 -0
- package/courses/mysql-query-optimization/scenarios/level-1/join-basics.yaml +66 -0
- package/courses/mysql-query-optimization/scenarios/level-1/n-plus-one-queries.yaml +67 -0
- package/courses/mysql-query-optimization/scenarios/level-1/query-rewriting-basics.yaml +66 -0
- package/courses/mysql-query-optimization/scenarios/level-1/select-star-problems.yaml +68 -0
- package/courses/mysql-query-optimization/scenarios/level-1/slow-query-diagnosis.yaml +65 -0
- package/courses/mysql-query-optimization/scenarios/level-1/where-clause-optimization.yaml +65 -0
- package/courses/mysql-query-optimization/scenarios/level-2/buffer-pool-tuning.yaml +64 -0
- package/courses/mysql-query-optimization/scenarios/level-2/composite-index-design.yaml +71 -0
- package/courses/mysql-query-optimization/scenarios/level-2/covering-and-invisible-indexes.yaml +69 -0
- package/courses/mysql-query-optimization/scenarios/level-2/cte-and-window-functions.yaml +78 -0
- package/courses/mysql-query-optimization/scenarios/level-2/intermediate-optimization-shift.yaml +68 -0
- package/courses/mysql-query-optimization/scenarios/level-2/join-optimization.yaml +67 -0
- package/courses/mysql-query-optimization/scenarios/level-2/performance-schema-analysis.yaml +69 -0
- package/courses/mysql-query-optimization/scenarios/level-2/query-optimizer-hints.yaml +74 -0
- package/courses/mysql-query-optimization/scenarios/level-2/subquery-optimization.yaml +70 -0
- package/courses/mysql-query-optimization/scenarios/level-2/write-optimization.yaml +63 -0
- package/courses/mysql-query-optimization/scenarios/level-3/advanced-optimization-shift.yaml +71 -0
- package/courses/mysql-query-optimization/scenarios/level-3/connection-management.yaml +67 -0
- package/courses/mysql-query-optimization/scenarios/level-3/full-text-search.yaml +77 -0
- package/courses/mysql-query-optimization/scenarios/level-3/json-optimization.yaml +87 -0
- package/courses/mysql-query-optimization/scenarios/level-3/lock-contention-analysis.yaml +68 -0
- package/courses/mysql-query-optimization/scenarios/level-3/monitoring-alerting.yaml +63 -0
- package/courses/mysql-query-optimization/scenarios/level-3/online-schema-changes.yaml +79 -0
- package/courses/mysql-query-optimization/scenarios/level-3/partitioning-strategies.yaml +83 -0
- package/courses/mysql-query-optimization/scenarios/level-3/query-profiling-deep-dive.yaml +84 -0
- package/courses/mysql-query-optimization/scenarios/level-3/replication-optimization.yaml +66 -0
- package/courses/mysql-query-optimization/scenarios/level-4/aurora-vs-rds-evaluation.yaml +61 -0
- package/courses/mysql-query-optimization/scenarios/level-4/data-architecture.yaml +62 -0
- package/courses/mysql-query-optimization/scenarios/level-4/database-migration-planning.yaml +59 -0
- package/courses/mysql-query-optimization/scenarios/level-4/enterprise-governance.yaml +50 -0
- package/courses/mysql-query-optimization/scenarios/level-4/executive-communication.yaml +54 -0
- package/courses/mysql-query-optimization/scenarios/level-4/expert-optimization-shift.yaml +67 -0
- package/courses/mysql-query-optimization/scenarios/level-4/high-availability-architecture.yaml +60 -0
- package/courses/mysql-query-optimization/scenarios/level-4/optimizer-internals.yaml +62 -0
- package/courses/mysql-query-optimization/scenarios/level-4/performance-sla-design.yaml +52 -0
- package/courses/mysql-query-optimization/scenarios/level-4/read-replica-scaling.yaml +51 -0
- package/courses/mysql-query-optimization/scenarios/level-5/ai-database-future.yaml +45 -0
- package/courses/mysql-query-optimization/scenarios/level-5/behavioral-science.yaml +44 -0
- package/courses/mysql-query-optimization/scenarios/level-5/benchmark-design.yaml +47 -0
- package/courses/mysql-query-optimization/scenarios/level-5/board-strategy.yaml +48 -0
- package/courses/mysql-query-optimization/scenarios/level-5/comprehensive-platform.yaml +49 -0
- package/courses/mysql-query-optimization/scenarios/level-5/consulting-engagement.yaml +52 -0
- package/courses/mysql-query-optimization/scenarios/level-5/ma-database-integration.yaml +47 -0
- package/courses/mysql-query-optimization/scenarios/level-5/master-optimization-shift.yaml +56 -0
- package/courses/mysql-query-optimization/scenarios/level-5/product-development.yaml +48 -0
- package/courses/mysql-query-optimization/scenarios/level-5/regulatory-compliance.yaml +48 -0
- package/courses/postgresql-query-optimization/scenarios/level-5/comprehensive-database-system.yaml +70 -0
- package/courses/postgresql-query-optimization/scenarios/level-5/database-ai-future.yaml +81 -0
- package/courses/postgresql-query-optimization/scenarios/level-5/database-behavioral-science.yaml +63 -0
- package/courses/postgresql-query-optimization/scenarios/level-5/database-board-strategy.yaml +77 -0
- package/courses/postgresql-query-optimization/scenarios/level-5/database-consulting-engagement.yaml +61 -0
- package/courses/postgresql-query-optimization/scenarios/level-5/database-industry-benchmarks.yaml +64 -0
- package/courses/postgresql-query-optimization/scenarios/level-5/database-ma-integration.yaml +71 -0
- package/courses/postgresql-query-optimization/scenarios/level-5/database-product-development.yaml +72 -0
- package/courses/postgresql-query-optimization/scenarios/level-5/database-regulatory-landscape.yaml +76 -0
- package/courses/postgresql-query-optimization/scenarios/level-5/master-optimization-shift.yaml +66 -0
- package/courses/terraform-infrastructure-setup/course.yaml +11 -0
- package/courses/terraform-infrastructure-setup/scenarios/level-1/terraform-init-errors.yaml +72 -0
- package/dist/mcp/session-manager.d.ts +7 -4
- package/dist/mcp/session-manager.d.ts.map +1 -1
- package/dist/mcp/session-manager.js +23 -8
- package/dist/mcp/session-manager.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
meta:
|
|
2
|
+
id: join-basics
|
|
3
|
+
level: 1
|
|
4
|
+
course: mysql-query-optimization
|
|
5
|
+
type: output
|
|
6
|
+
description: "Understand MySQL JOIN execution — learn how MySQL processes JOINs, the nested-loop algorithm, and how to optimize JOIN queries with indexes"
|
|
7
|
+
tags: [MySQL, JOIN, nested-loop, hash-join, index, beginner]
|
|
8
|
+
|
|
9
|
+
state: {}
|
|
10
|
+
|
|
11
|
+
trigger: |
|
|
12
|
+
You're building a report that shows order details with customer and
|
|
13
|
+
product information. Your query joins 4 tables and takes 30 seconds:
|
|
14
|
+
|
|
15
|
+
SELECT o.id, o.total, c.name, c.email,
|
|
16
|
+
oi.quantity, oi.unit_price, p.name AS product_name
|
|
17
|
+
FROM orders o
|
|
18
|
+
JOIN customers c ON c.id = o.customer_id
|
|
19
|
+
JOIN order_items oi ON oi.order_id = o.id
|
|
20
|
+
JOIN products p ON p.id = oi.product_id
|
|
21
|
+
WHERE o.created_at >= '2025-01-01'
|
|
22
|
+
AND o.status = 'completed';
|
|
23
|
+
|
|
24
|
+
EXPLAIN output:
|
|
25
|
+
+----+-------+--------+------+---------------+------+--------+-----------+
|
|
26
|
+
| id | table | type | key | rows | filt | Extra |
|
|
27
|
+
+----+-------+--------+------+---------------+------+--------+-----------+
|
|
28
|
+
| 1 | o | ALL | NULL | 5,000,000 | 5.00 | Using where |
|
|
29
|
+
| 1 | c | eq_ref | PK | 1 | 100 | NULL |
|
|
30
|
+
| 1 | oi | ref | idx_order_id | 3 | 100 | NULL |
|
|
31
|
+
| 1 | p | eq_ref | PK | 1 | 100 | NULL |
|
|
32
|
+
+----+-------+--------+------+---------------+------+--------+-----------+
|
|
33
|
+
|
|
34
|
+
The issue: orders table has type=ALL (full table scan of 5M rows).
|
|
35
|
+
MySQL then does a nested loop: for each of the 5M order rows, it
|
|
36
|
+
looks up the customer (eq_ref, fast), finds order items (ref, ~3 per
|
|
37
|
+
order), and looks up each product (eq_ref, fast).
|
|
38
|
+
|
|
39
|
+
But the first step scans all 5M orders when only ~250K match the
|
|
40
|
+
WHERE clause (status='completed' AND created_at >= '2025-01-01').
|
|
41
|
+
|
|
42
|
+
Available indexes:
|
|
43
|
+
- orders: PRIMARY(id), idx_customer_id(customer_id)
|
|
44
|
+
- customers: PRIMARY(id)
|
|
45
|
+
- order_items: PRIMARY(id), idx_order_id(order_id)
|
|
46
|
+
- products: PRIMARY(id)
|
|
47
|
+
|
|
48
|
+
Task: Explain how MySQL executes JOINs. Write: the nested-loop join
|
|
49
|
+
algorithm (how MySQL processes joins step by step), why join order
|
|
50
|
+
matters (driving table selection), why the orders table needs a better
|
|
51
|
+
index, how eq_ref vs ref vs ALL access types affect join performance,
|
|
52
|
+
and how MySQL 8.0's hash join changes things.
|
|
53
|
+
|
|
54
|
+
assertions:
|
|
55
|
+
- type: llm_judge
|
|
56
|
+
criteria: "Nested-loop join is explained — MySQL traditionally uses nested-loop join: for each row in the outer (driving) table, it looks up matching rows in the inner table using the join condition. The optimizer chooses the join order to minimize total rows examined. Currently the orders full table scan drives 5M iterations"
|
|
57
|
+
weight: 0.35
|
|
58
|
+
description: "Nested-loop algorithm explained"
|
|
59
|
+
- type: llm_judge
|
|
60
|
+
criteria: "Index fix is recommended — a composite index on orders(status, created_at) or orders(created_at, status) would allow MySQL to use a range scan instead of a full table scan on the driving table, reducing rows from 5M to ~250K. Explains that the join itself (eq_ref for customers and products) is already optimal"
|
|
61
|
+
weight: 0.35
|
|
62
|
+
description: "Index fix recommended"
|
|
63
|
+
- type: llm_judge
|
|
64
|
+
criteria: "MySQL 8.0 hash join is mentioned — MySQL 8.0.18+ introduced hash join for equi-joins without indexes (builds hash table on smaller table, probes with larger table). Hash join is used when there's no usable index on the join column. It's an alternative to block nested-loop join, not a replacement for indexed nested-loop"
|
|
65
|
+
weight: 0.30
|
|
66
|
+
description: "Hash join mentioned"
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
meta:
|
|
2
|
+
id: n-plus-one-queries
|
|
3
|
+
level: 1
|
|
4
|
+
course: mysql-query-optimization
|
|
5
|
+
type: output
|
|
6
|
+
description: "Detect and fix N+1 queries — identify the pattern in ORM-generated SQL and resolve with eager loading or query restructuring"
|
|
7
|
+
tags: [MySQL, N+1, ORM, eager-loading, performance, beginner]
|
|
8
|
+
|
|
9
|
+
state: {}
|
|
10
|
+
|
|
11
|
+
trigger: |
|
|
12
|
+
Your API endpoint /api/orders takes 12 seconds to return 100 orders.
|
|
13
|
+
You enable the MySQL slow query log and discover that the endpoint
|
|
14
|
+
executes 301 queries:
|
|
15
|
+
|
|
16
|
+
-- Query 1: Get orders
|
|
17
|
+
SELECT * FROM orders WHERE user_id = 42 ORDER BY created_at DESC LIMIT 100;
|
|
18
|
+
-- 0.5ms
|
|
19
|
+
|
|
20
|
+
-- Query 2-101: Get customer for each order (N times)
|
|
21
|
+
SELECT * FROM customers WHERE id = 1001; -- 0.3ms
|
|
22
|
+
SELECT * FROM customers WHERE id = 1002; -- 0.3ms
|
|
23
|
+
SELECT * FROM customers WHERE id = 1003; -- 0.3ms
|
|
24
|
+
... (98 more)
|
|
25
|
+
|
|
26
|
+
-- Query 102-201: Get order items for each order (N times)
|
|
27
|
+
SELECT * FROM order_items WHERE order_id = 5001; -- 0.4ms
|
|
28
|
+
SELECT * FROM order_items WHERE order_id = 5002; -- 0.4ms
|
|
29
|
+
... (98 more)
|
|
30
|
+
|
|
31
|
+
-- Query 202-301: Get product for each order item (N times)
|
|
32
|
+
SELECT * FROM products WHERE id = 8001; -- 0.3ms
|
|
33
|
+
SELECT * FROM products WHERE id = 8002; -- 0.3ms
|
|
34
|
+
... (98 more)
|
|
35
|
+
|
|
36
|
+
Each individual query is fast (0.3-0.5ms), but the total is:
|
|
37
|
+
1 + 100 + 100 + 100 = 301 queries × ~0.35ms = ~105ms query time
|
|
38
|
+
But with network round-trip overhead: 301 × ~40ms = 12 seconds
|
|
39
|
+
|
|
40
|
+
The ORM code that generates this:
|
|
41
|
+
orders = Order.find_by_user(user_id=42, limit=100)
|
|
42
|
+
for order in orders:
|
|
43
|
+
order.customer = Customer.find(order.customer_id)
|
|
44
|
+
order.items = OrderItem.find_by_order(order.id)
|
|
45
|
+
for item in order.items:
|
|
46
|
+
item.product = Product.find(item.product_id)
|
|
47
|
+
|
|
48
|
+
Task: Explain the N+1 query problem and how to fix it. Write: why
|
|
49
|
+
this pattern is slow (network round trips, not query execution), how
|
|
50
|
+
to detect it (query count monitoring, slow query log patterns), the
|
|
51
|
+
JOIN-based solution (single query with JOINs), the IN-based solution
|
|
52
|
+
(batch loading with WHERE id IN (...)), and which ORM features help
|
|
53
|
+
(eager loading, batch size configuration).
|
|
54
|
+
|
|
55
|
+
assertions:
|
|
56
|
+
- type: llm_judge
|
|
57
|
+
criteria: "N+1 problem is correctly identified — 1 query to get the list + N queries per related entity = N+1 pattern. The bottleneck is network round-trip latency (not query execution), which is why each query is fast individually but the total is slow. 301 round trips at 40ms each dominates the 12-second response time"
|
|
58
|
+
weight: 0.35
|
|
59
|
+
description: "N+1 problem identified"
|
|
60
|
+
- type: llm_judge
|
|
61
|
+
criteria: "Solutions are provided — JOIN solution (single query joining orders, customers, order_items, products), IN-based batch loading (SELECT * FROM customers WHERE id IN (1001, 1002, ...)), and ORM eager loading patterns. Explains trade-offs: JOINs may return duplicate data for one-to-many, while IN-based loading keeps queries separate but reduces to 4 queries total"
|
|
62
|
+
weight: 0.35
|
|
63
|
+
description: "Multiple solutions provided"
|
|
64
|
+
- type: llm_judge
|
|
65
|
+
criteria: "Detection methods are explained — monitoring query count per request, enabling slow query log with low threshold, using MySQL Performance Schema (events_statements_summary_by_digest) to find high-frequency simple queries, and ORM-level query logging to catch the pattern during development"
|
|
66
|
+
weight: 0.30
|
|
67
|
+
description: "Detection methods explained"
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
meta:
|
|
2
|
+
id: query-rewriting-basics
|
|
3
|
+
level: 1
|
|
4
|
+
course: mysql-query-optimization
|
|
5
|
+
type: output
|
|
6
|
+
description: "Rewrite inefficient MySQL queries — transform common slow patterns into optimized equivalents using indexes, limits, and restructured logic"
|
|
7
|
+
tags: [MySQL, query-rewriting, optimization, patterns, beginner]
|
|
8
|
+
|
|
9
|
+
state: {}
|
|
10
|
+
|
|
11
|
+
trigger: |
|
|
12
|
+
Your team lead asks you to review 6 queries flagged by the DBA as
|
|
13
|
+
"query optimization opportunities." Each query works correctly but
|
|
14
|
+
can be rewritten to be significantly faster.
|
|
15
|
+
|
|
16
|
+
Query 1 — Counting with full scan:
|
|
17
|
+
SELECT COUNT(*) FROM orders WHERE status = 'pending';
|
|
18
|
+
-- Takes 3 seconds on 10M rows, even with index on status
|
|
19
|
+
-- Because COUNT(*) must visit every matching row
|
|
20
|
+
|
|
21
|
+
Query 2 — Existence check with COUNT:
|
|
22
|
+
SELECT COUNT(*) FROM users WHERE email = 'john@example.com';
|
|
23
|
+
-- Application checks: if (count > 0) { user_exists = true }
|
|
24
|
+
-- Scans all matching rows just to check existence
|
|
25
|
+
|
|
26
|
+
Query 3 — DISTINCT with large result set:
|
|
27
|
+
SELECT DISTINCT customer_id FROM orders
|
|
28
|
+
WHERE created_at >= '2025-01-01';
|
|
29
|
+
-- Returns 500K distinct customer IDs from 5M orders
|
|
30
|
+
-- Creates a temporary table and sorts
|
|
31
|
+
|
|
32
|
+
Query 4 — Sorting large result sets:
|
|
33
|
+
SELECT * FROM products ORDER BY popularity DESC;
|
|
34
|
+
-- Returns all 1M products sorted, but UI shows only top 20
|
|
35
|
+
-- Sorts 1M rows in memory or on disk
|
|
36
|
+
|
|
37
|
+
Query 5 — Correlated subquery:
|
|
38
|
+
SELECT * FROM customers c
|
|
39
|
+
WHERE (SELECT MAX(created_at) FROM orders
|
|
40
|
+
WHERE customer_id = c.id) >= '2025-01-01';
|
|
41
|
+
-- Executes the subquery once per customer (500K times)
|
|
42
|
+
|
|
43
|
+
Query 6 — UNION when UNION ALL works:
|
|
44
|
+
SELECT name FROM products WHERE category = 'electronics'
|
|
45
|
+
UNION
|
|
46
|
+
SELECT name FROM products WHERE category = 'computers';
|
|
47
|
+
-- UNION removes duplicates (requires sort + dedup)
|
|
48
|
+
-- Categories are mutually exclusive, so no duplicates possible
|
|
49
|
+
|
|
50
|
+
Task: Rewrite each query for better performance. Write: the optimized
|
|
51
|
+
version of each query, why the original is slow, what technique makes
|
|
52
|
+
it faster, and the general principle behind each optimization.
|
|
53
|
+
|
|
54
|
+
assertions:
|
|
55
|
+
- type: llm_judge
|
|
56
|
+
criteria: "All 6 rewrites are correct — (1) maintain a counter table or use approximate count, or accept the cost if exact count is needed, (2) SELECT EXISTS or SELECT 1 ... LIMIT 1, (3) consider GROUP BY or index-only scan, (4) add LIMIT 20, (5) convert to JOIN (JOIN orders ON... WHERE orders.created_at >= ...), (6) UNION ALL since categories are mutually exclusive"
|
|
57
|
+
weight: 0.35
|
|
58
|
+
description: "All rewrites correct"
|
|
59
|
+
- type: llm_judge
|
|
60
|
+
criteria: "Performance impact is explained — each rewrite explains why it's faster (fewer rows examined, less sorting, avoiding temporary tables, reducing subquery executions from N to 1, removing unnecessary deduplication)"
|
|
61
|
+
weight: 0.35
|
|
62
|
+
description: "Performance impact explained"
|
|
63
|
+
- type: llm_judge
|
|
64
|
+
criteria: "General principles are extracted — always add LIMIT when you only need a subset, use EXISTS instead of COUNT for existence checks, use UNION ALL when duplicates aren't possible, convert correlated subqueries to JOINs, avoid sorting more data than needed"
|
|
65
|
+
weight: 0.30
|
|
66
|
+
description: "General principles extracted"
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
meta:
|
|
2
|
+
id: select-star-problems
|
|
3
|
+
level: 1
|
|
4
|
+
course: mysql-query-optimization
|
|
5
|
+
type: output
|
|
6
|
+
description: "Understand why SELECT * hurts performance — learn about unnecessary I/O, buffer pool waste, and covering index defeat in MySQL"
|
|
7
|
+
tags: [MySQL, SELECT-star, InnoDB, buffer-pool, covering-index, beginner]
|
|
8
|
+
|
|
9
|
+
state: {}
|
|
10
|
+
|
|
11
|
+
trigger: |
|
|
12
|
+
Your team's API is consuming excessive memory and the MySQL server's
|
|
13
|
+
buffer pool hit ratio has dropped from 99% to 85%. Investigation
|
|
14
|
+
reveals that almost every query uses SELECT *. A senior DBA says
|
|
15
|
+
"SELECT * is killing our buffer pool." You need to understand why.
|
|
16
|
+
|
|
17
|
+
Example queries and their impact:
|
|
18
|
+
|
|
19
|
+
1. User list endpoint:
|
|
20
|
+
SELECT * FROM users WHERE status = 'active' LIMIT 50;
|
|
21
|
+
-- users table has 45 columns including a TEXT bio and BLOB avatar
|
|
22
|
+
-- Only the API needs: id, name, email, avatar_url (4 columns)
|
|
23
|
+
-- Result: 50 rows × 45 columns instead of 50 × 4
|
|
24
|
+
|
|
25
|
+
2. Order count:
|
|
26
|
+
SELECT * FROM orders WHERE customer_id = 123;
|
|
27
|
+
-- Then the application does: orders.length
|
|
28
|
+
-- The application only needs COUNT(*), not the actual rows
|
|
29
|
+
-- Result: transfers 500 rows (with JSON payload column) just to count
|
|
30
|
+
|
|
31
|
+
3. Existence check:
|
|
32
|
+
SELECT * FROM users WHERE email = 'john@example.com';
|
|
33
|
+
-- Then: if (result) { ... }
|
|
34
|
+
-- Only needs SELECT 1 or SELECT EXISTS
|
|
35
|
+
-- Result: loads entire row with all 45 columns to check existence
|
|
36
|
+
|
|
37
|
+
4. Covering index defeat:
|
|
38
|
+
-- Index exists: idx_status_email (status, email)
|
|
39
|
+
SELECT * FROM users WHERE status = 'active';
|
|
40
|
+
-- EXPLAIN: type=ref, Extra=NULL (reads full rows from clustered index)
|
|
41
|
+
SELECT status, email FROM users WHERE status = 'active';
|
|
42
|
+
-- EXPLAIN: type=ref, Extra=Using index (index-only scan!)
|
|
43
|
+
|
|
44
|
+
InnoDB buffer pool stats:
|
|
45
|
+
- Buffer pool size: 8GB
|
|
46
|
+
- Pages read from disk: 50K/hour (was 5K/hour before traffic growth)
|
|
47
|
+
- Buffer pool hit ratio: 85% (target: 99%+)
|
|
48
|
+
- Average row size: 2.4KB (would be 200 bytes with explicit columns)
|
|
49
|
+
|
|
50
|
+
Task: Explain why SELECT * is a performance problem. Write: how it
|
|
51
|
+
wastes I/O and memory (InnoDB buffer pool impact), how it defeats
|
|
52
|
+
covering indexes, when it prevents query optimization, what the
|
|
53
|
+
correct practice is (explicit column lists), and exceptions where
|
|
54
|
+
SELECT * is acceptable.
|
|
55
|
+
|
|
56
|
+
assertions:
|
|
57
|
+
- type: llm_judge
|
|
58
|
+
criteria: "I/O and buffer pool impact is explained — SELECT * reads entire rows from the clustered index including large columns (TEXT, BLOB, JSON), filling the buffer pool with unnecessary data and evicting hot pages. With explicit columns, InnoDB may satisfy the query from a smaller secondary index (covering index), keeping the buffer pool efficient"
|
|
59
|
+
weight: 0.35
|
|
60
|
+
description: "Buffer pool impact explained"
|
|
61
|
+
- type: llm_judge
|
|
62
|
+
criteria: "Covering index defeat is explained — when SELECT * is used, MySQL must read the full row from the clustered index even if a secondary index matches the WHERE clause. With explicit columns that are all in the index, MySQL can use an index-only scan (Using index in EXPLAIN), avoiding the clustered index entirely"
|
|
63
|
+
weight: 0.35
|
|
64
|
+
description: "Covering index defeat explained"
|
|
65
|
+
- type: llm_judge
|
|
66
|
+
criteria: "Practical guidance is provided — always specify needed columns, use COUNT(*) for counts, use SELECT EXISTS or SELECT 1 ... LIMIT 1 for existence checks, and notes exceptions (ad-hoc debugging queries, tables with few small columns, ORM code that needs all fields for object hydration)"
|
|
67
|
+
weight: 0.30
|
|
68
|
+
description: "Practical guidance"
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
meta:
|
|
2
|
+
id: slow-query-diagnosis
|
|
3
|
+
level: 1
|
|
4
|
+
course: mysql-query-optimization
|
|
5
|
+
type: output
|
|
6
|
+
description: "Diagnose slow MySQL queries — use the slow query log, Performance Schema, and SHOW PROCESSLIST to find and analyze problematic queries"
|
|
7
|
+
tags: [MySQL, slow-query-log, Performance-Schema, diagnosis, beginner]
|
|
8
|
+
|
|
9
|
+
state: {}
|
|
10
|
+
|
|
11
|
+
trigger: |
|
|
12
|
+
Users are reporting that "the app is slow." You need to find which
|
|
13
|
+
queries are causing the problem, but you don't know where to start.
|
|
14
|
+
You have access to a MySQL 8.0 production server.
|
|
15
|
+
|
|
16
|
+
Current configuration:
|
|
17
|
+
- slow_query_log = OFF (never been enabled)
|
|
18
|
+
- long_query_time = 10 (default — only logs queries >10 seconds)
|
|
19
|
+
- performance_schema = ON (default in MySQL 8.0)
|
|
20
|
+
|
|
21
|
+
When you run SHOW PROCESSLIST:
|
|
22
|
+
+----+------+-------+------+---------+------+----------+----------------------+
|
|
23
|
+
| Id | User | Host | db | Command | Time | State | Info |
|
|
24
|
+
+----+------+-------+------+---------+------+----------+----------------------+
|
|
25
|
+
| 45 | app | ... | shop | Query | 120 | Sending | SELECT * FROM ord... |
|
|
26
|
+
| 46 | app | ... | shop | Query | 85 | Sorting | SELECT p.*, COUNT... |
|
|
27
|
+
| 47 | app | ... | shop | Query | 0 | executing| SELECT id FROM u... |
|
|
28
|
+
| 48 | app | ... | shop | Sleep | 300 | NULL | NULL |
|
|
29
|
+
| 49 | app | ... | shop | Query | 45 | Locked | UPDATE inventory ... |
|
|
30
|
+
+----+------+-------+------+---------+------+----------+----------------------+
|
|
31
|
+
(plus 195 more connections, mostly in Sleep state)
|
|
32
|
+
|
|
33
|
+
You also check Performance Schema:
|
|
34
|
+
SELECT DIGEST_TEXT, COUNT_STAR, AVG_TIMER_WAIT/1000000000 AS avg_ms,
|
|
35
|
+
SUM_ROWS_EXAMINED, SUM_ROWS_SENT
|
|
36
|
+
FROM performance_schema.events_statements_summary_by_digest
|
|
37
|
+
ORDER BY SUM_TIMER_WAIT DESC LIMIT 5;
|
|
38
|
+
|
|
39
|
+
Top 5 queries by total time:
|
|
40
|
+
1. SELECT * FROM orders WHERE... — 50K executions, avg 200ms, 10M rows examined
|
|
41
|
+
2. SELECT p.*, COUNT(r.*)... — 5K executions, avg 3 seconds, 50M rows examined
|
|
42
|
+
3. UPDATE inventory SET... — 20K executions, avg 150ms (but high lock waits)
|
|
43
|
+
4. SELECT * FROM products... — 100K executions, avg 50ms, 500K rows examined
|
|
44
|
+
5. INSERT INTO audit_log... — 200K executions, avg 5ms (low individual but high total)
|
|
45
|
+
|
|
46
|
+
Task: Explain how to diagnose slow queries in MySQL. Write: how to
|
|
47
|
+
enable and configure the slow query log (what settings to change),
|
|
48
|
+
how to read SHOW PROCESSLIST output (what each column and state means),
|
|
49
|
+
how to use Performance Schema for query analysis, how to identify the
|
|
50
|
+
highest-impact query to optimize first, and the initial investigation
|
|
51
|
+
steps for each of the 5 top queries.
|
|
52
|
+
|
|
53
|
+
assertions:
|
|
54
|
+
- type: llm_judge
|
|
55
|
+
criteria: "Slow query log configuration is correct — SET GLOBAL slow_query_log = ON, lower long_query_time to 1 second (or lower), enable log_queries_not_using_indexes, and explains where to find the log file. Mentions pt-query-digest or mysqldumpslow for analyzing the log"
|
|
56
|
+
weight: 0.35
|
|
57
|
+
description: "Slow query log setup"
|
|
58
|
+
- type: llm_judge
|
|
59
|
+
criteria: "PROCESSLIST analysis identifies issues — the 120-second query is a major problem (likely full table scan), the Sorting state indicates filesort on large result, the Locked state indicates lock contention, the 300-second Sleep is a connection leak. Each state is explained and the severity is assessed"
|
|
60
|
+
weight: 0.35
|
|
61
|
+
description: "PROCESSLIST analysis"
|
|
62
|
+
- type: llm_judge
|
|
63
|
+
criteria: "Performance Schema analysis prioritizes correctly — identifies query #2 (3-second avg, 50M rows) as highest impact for optimization, explains why total time matters more than individual execution time for query #5, and recommends investigating the rows_examined vs rows_sent ratio as a key efficiency metric"
|
|
64
|
+
weight: 0.30
|
|
65
|
+
description: "Performance Schema prioritization"
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
meta:
|
|
2
|
+
id: where-clause-optimization
|
|
3
|
+
level: 1
|
|
4
|
+
course: mysql-query-optimization
|
|
5
|
+
type: output
|
|
6
|
+
description: "Optimize WHERE clauses in MySQL — write SARGable conditions, avoid function wrapping, and understand how MySQL uses indexes for filtering"
|
|
7
|
+
tags: [MySQL, WHERE, SARGable, index-usage, filtering, beginner]
|
|
8
|
+
|
|
9
|
+
state: {}
|
|
10
|
+
|
|
11
|
+
trigger: |
|
|
12
|
+
You're reviewing slow queries found in the slow query log. Several
|
|
13
|
+
queries have indexes available but MySQL isn't using them. The
|
|
14
|
+
EXPLAIN output shows type=ALL (full table scan) despite relevant
|
|
15
|
+
indexes existing.
|
|
16
|
+
|
|
17
|
+
Problematic queries (all have indexes on the filtered columns):
|
|
18
|
+
|
|
19
|
+
1. Date range query (index on created_at):
|
|
20
|
+
SELECT * FROM orders
|
|
21
|
+
WHERE YEAR(created_at) = 2025 AND MONTH(created_at) = 12;
|
|
22
|
+
-- EXPLAIN: type=ALL, rows=5M (ignores index)
|
|
23
|
+
|
|
24
|
+
2. Case-insensitive search (index on email):
|
|
25
|
+
SELECT * FROM users WHERE LOWER(email) = 'john@example.com';
|
|
26
|
+
-- EXPLAIN: type=ALL, rows=2M (ignores index)
|
|
27
|
+
|
|
28
|
+
3. String pattern search (index on name):
|
|
29
|
+
SELECT * FROM products WHERE name LIKE '%widget%';
|
|
30
|
+
-- EXPLAIN: type=ALL, rows=1M (ignores index)
|
|
31
|
+
|
|
32
|
+
4. Math on column (index on price):
|
|
33
|
+
SELECT * FROM products WHERE price * 1.1 > 50;
|
|
34
|
+
-- EXPLAIN: type=ALL, rows=1M (ignores index)
|
|
35
|
+
|
|
36
|
+
5. Implicit type conversion (index on phone VARCHAR):
|
|
37
|
+
SELECT * FROM customers WHERE phone = 5551234567;
|
|
38
|
+
-- EXPLAIN: type=ALL, rows=500K (ignores index)
|
|
39
|
+
|
|
40
|
+
6. OR with different columns (indexes on status and priority):
|
|
41
|
+
SELECT * FROM tickets
|
|
42
|
+
WHERE status = 'open' OR priority = 'high';
|
|
43
|
+
-- EXPLAIN: type=ALL, rows=2M (ignores both indexes)
|
|
44
|
+
|
|
45
|
+
Each query has an appropriate index, but the WHERE clause is written
|
|
46
|
+
in a way that prevents MySQL from using it.
|
|
47
|
+
|
|
48
|
+
Task: Explain why each query can't use its index and how to rewrite
|
|
49
|
+
it. Write: what "SARGable" means, why functions on indexed columns
|
|
50
|
+
prevent index usage, the correct rewrite for each of the 6 queries,
|
|
51
|
+
and general rules for writing index-friendly WHERE clauses.
|
|
52
|
+
|
|
53
|
+
assertions:
|
|
54
|
+
- type: llm_judge
|
|
55
|
+
criteria: "SARGable is explained — Search ARGument ABLE means the condition can use an index. Functions, math, or type conversions on the indexed column prevent index usage because MySQL can't use the B-tree to look up transformed values. The condition must isolate the column on one side of the comparison"
|
|
56
|
+
weight: 0.35
|
|
57
|
+
description: "SARGable concept explained"
|
|
58
|
+
- type: llm_judge
|
|
59
|
+
criteria: "All 6 rewrites are correct — (1) created_at >= '2025-12-01' AND created_at < '2026-01-01', (2) email = 'john@example.com' (MySQL default collation is case-insensitive) or use a generated column with expression index, (3) full-text index or application-level search (leading wildcard can't use B-tree), (4) price > 50/1.1 (move math to the constant side), (5) phone = '5551234567' (match the column type), (6) UNION of two queries or index_merge optimization"
|
|
60
|
+
weight: 0.35
|
|
61
|
+
description: "Correct rewrites for all 6"
|
|
62
|
+
- type: llm_judge
|
|
63
|
+
criteria: "General rules are provided — never apply functions to indexed columns, keep the indexed column alone on one side, match data types to avoid implicit conversion, leading wildcards can't use B-tree indexes, OR across different columns may prevent index usage (consider UNION or index_merge)"
|
|
64
|
+
weight: 0.30
|
|
65
|
+
description: "General SARGable rules"
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
meta:
|
|
2
|
+
id: buffer-pool-tuning
|
|
3
|
+
level: 2
|
|
4
|
+
course: mysql-query-optimization
|
|
5
|
+
type: output
|
|
6
|
+
description: "Tune InnoDB buffer pool — configure pool size, instances, and flushing for optimal read/write performance"
|
|
7
|
+
tags: [MySQL, InnoDB, buffer-pool, tuning, memory, intermediate]
|
|
8
|
+
|
|
9
|
+
state: {}
|
|
10
|
+
|
|
11
|
+
trigger: |
|
|
12
|
+
You've been asked to tune a MySQL 8.0 server that's performing poorly.
|
|
13
|
+
The server has 128GB RAM but was set up with default settings. You
|
|
14
|
+
need to configure the buffer pool and related settings for a mixed
|
|
15
|
+
OLTP/reporting workload.
|
|
16
|
+
|
|
17
|
+
Server specs:
|
|
18
|
+
- RAM: 128GB
|
|
19
|
+
- CPU: 32 cores
|
|
20
|
+
- Storage: NVMe SSD (500K IOPS)
|
|
21
|
+
- MySQL data size: 200GB (data + indexes)
|
|
22
|
+
- Workload: 70% reads, 30% writes, 50K QPS peak
|
|
23
|
+
|
|
24
|
+
Current settings (defaults):
|
|
25
|
+
innodb_buffer_pool_size = 128M (0.1% of RAM!)
|
|
26
|
+
innodb_buffer_pool_instances = 1
|
|
27
|
+
innodb_buffer_pool_chunk_size = 128M
|
|
28
|
+
innodb_log_file_size = 48M
|
|
29
|
+
innodb_io_capacity = 200
|
|
30
|
+
innodb_io_capacity_max = 2000
|
|
31
|
+
innodb_flush_log_at_trx_commit = 1
|
|
32
|
+
innodb_flush_method = fsync
|
|
33
|
+
|
|
34
|
+
Current symptoms:
|
|
35
|
+
- Buffer pool hit ratio: 65% (terrible)
|
|
36
|
+
- Innodb_buffer_pool_reads: 500K/hour (disk reads)
|
|
37
|
+
- Innodb_buffer_pool_pages_dirty: fluctuates wildly (200 to 8000)
|
|
38
|
+
- Innodb_log_waits: 50K/hour (log writes stalling)
|
|
39
|
+
- CPU usage: 20% (mostly waiting on I/O)
|
|
40
|
+
- Disk read latency: 0.5ms (NVMe is fast, but too many reads)
|
|
41
|
+
|
|
42
|
+
The data team runs nightly reports (full table scans on 50GB tables)
|
|
43
|
+
that flush the buffer pool, causing morning performance degradation.
|
|
44
|
+
|
|
45
|
+
Task: Design the buffer pool tuning configuration. Write: the
|
|
46
|
+
recommended innodb_buffer_pool_size (with calculation), the instance
|
|
47
|
+
and chunk size configuration, the flushing strategy (io_capacity,
|
|
48
|
+
flush_method, log_file_size), how to handle the nightly report
|
|
49
|
+
buffer pool pollution, and the monitoring queries to validate
|
|
50
|
+
improvements.
|
|
51
|
+
|
|
52
|
+
assertions:
|
|
53
|
+
- type: llm_judge
|
|
54
|
+
criteria: "Buffer pool sizing is correct — recommends 70-80% of RAM (90-100GB) for this dedicated MySQL server, explains why it can't cache the full 200GB dataset but should cache the hot working set, configures innodb_buffer_pool_instances to 8-16 for multi-core concurrency, and sets chunk_size appropriately (size must be multiple of chunk × instances)"
|
|
55
|
+
weight: 0.35
|
|
56
|
+
description: "Buffer pool sizing"
|
|
57
|
+
- type: llm_judge
|
|
58
|
+
criteria: "Flushing and logging are tuned — increases innodb_log_file_size to 1-4GB (reduces checkpoint frequency, eliminates log_waits), sets innodb_io_capacity to match NVMe capability (10K-50K), uses O_DIRECT flush method (avoids OS double-buffering), and explains the trade-off of innodb_flush_log_at_trx_commit=2 for the reporting workload"
|
|
59
|
+
weight: 0.35
|
|
60
|
+
description: "Flushing and logging tuned"
|
|
61
|
+
- type: llm_judge
|
|
62
|
+
criteria: "Buffer pool pollution from reports is addressed — explains InnoDB's midpoint insertion strategy (innodb_old_blocks_pct, innodb_old_blocks_time), how full table scans pollute the buffer pool by evicting hot pages, and solutions: tuning old_blocks_time to prevent scan pages from moving to young list, or running reports on a read replica"
|
|
63
|
+
weight: 0.30
|
|
64
|
+
description: "Buffer pool pollution addressed"
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
meta:
|
|
2
|
+
id: composite-index-design
|
|
3
|
+
level: 2
|
|
4
|
+
course: mysql-query-optimization
|
|
5
|
+
type: output
|
|
6
|
+
description: "Design composite indexes — understand column ordering, leftmost prefix rule, and how to cover multiple query patterns with fewer indexes"
|
|
7
|
+
tags: [MySQL, composite-index, column-ordering, leftmost-prefix, intermediate]
|
|
8
|
+
|
|
9
|
+
state: {}
|
|
10
|
+
|
|
11
|
+
trigger: |
|
|
12
|
+
Your e-commerce application has 8 different query patterns on the
|
|
13
|
+
orders table (50M rows), and the current 12 single-column indexes
|
|
14
|
+
are consuming 15GB of storage while not covering the most common
|
|
15
|
+
query patterns effectively.
|
|
16
|
+
|
|
17
|
+
The 8 query patterns (ordered by frequency):
|
|
18
|
+
|
|
19
|
+
1. (50K/day) Order lookup by customer:
|
|
20
|
+
WHERE customer_id = ? ORDER BY created_at DESC LIMIT 20
|
|
21
|
+
|
|
22
|
+
2. (30K/day) Recent orders by status:
|
|
23
|
+
WHERE status = ? AND created_at >= ? ORDER BY created_at DESC
|
|
24
|
+
|
|
25
|
+
3. (20K/day) Customer orders by status:
|
|
26
|
+
WHERE customer_id = ? AND status = ?
|
|
27
|
+
|
|
28
|
+
4. (10K/day) Date range with status:
|
|
29
|
+
WHERE created_at BETWEEN ? AND ? AND status = ?
|
|
30
|
+
|
|
31
|
+
5. (5K/day) Admin search:
|
|
32
|
+
WHERE status = ? AND total >= ? ORDER BY total DESC
|
|
33
|
+
|
|
34
|
+
6. (2K/day) Customer analytics:
|
|
35
|
+
SELECT customer_id, COUNT(*), SUM(total)
|
|
36
|
+
FROM orders WHERE created_at >= ? GROUP BY customer_id
|
|
37
|
+
|
|
38
|
+
7. (1K/day) Fulfillment queue:
|
|
39
|
+
WHERE status = 'pending' AND warehouse_id = ?
|
|
40
|
+
ORDER BY priority DESC, created_at ASC
|
|
41
|
+
|
|
42
|
+
8. (500/day) Revenue report:
|
|
43
|
+
SELECT DATE(created_at), SUM(total)
|
|
44
|
+
WHERE created_at BETWEEN ? AND ?
|
|
45
|
+
GROUP BY DATE(created_at)
|
|
46
|
+
|
|
47
|
+
Current single-column indexes:
|
|
48
|
+
idx_customer_id, idx_status, idx_created_at, idx_total,
|
|
49
|
+
idx_warehouse_id, idx_priority (plus 6 more on other columns)
|
|
50
|
+
|
|
51
|
+
Goal: Replace the 12 indexes with 4-5 well-designed composite indexes
|
|
52
|
+
that cover all 8 query patterns.
|
|
53
|
+
|
|
54
|
+
Task: Design the composite index strategy. Write: the indexes you
|
|
55
|
+
would create (with column order), which query patterns each index
|
|
56
|
+
serves, the leftmost prefix rule (why column order matters), how to
|
|
57
|
+
handle conflicting sort orders, and the storage savings estimate.
|
|
58
|
+
|
|
59
|
+
assertions:
|
|
60
|
+
- type: llm_judge
|
|
61
|
+
criteria: "Composite indexes are well-designed — proposes 4-5 indexes that cover all 8 query patterns using the leftmost prefix rule. For example: (customer_id, status, created_at), (status, created_at), (status, warehouse_id, priority, created_at). Column ordering follows equality-first, then range/sort"
|
|
62
|
+
weight: 0.35
|
|
63
|
+
description: "Well-designed composite indexes"
|
|
64
|
+
- type: llm_judge
|
|
65
|
+
criteria: "Leftmost prefix rule is explained — MySQL can use a composite index for queries that filter on the leftmost columns of the index. An index on (A, B, C) can serve queries on (A), (A, B), and (A, B, C) but NOT (B, C) or (C). This is why column order matters and why one composite index can serve multiple query patterns"
|
|
66
|
+
weight: 0.35
|
|
67
|
+
description: "Leftmost prefix rule"
|
|
68
|
+
- type: llm_judge
|
|
69
|
+
criteria: "Trade-offs are discussed — explains how equality columns should come before range columns in the index, why conflicting sort orders may need separate indexes, the write overhead of composite indexes (each insert/update must update all indexes), and the estimated storage reduction from 12 single-column to 4-5 composite indexes"
|
|
70
|
+
weight: 0.30
|
|
71
|
+
description: "Trade-offs discussed"
|
package/courses/mysql-query-optimization/scenarios/level-2/covering-and-invisible-indexes.yaml
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
meta:
|
|
2
|
+
id: covering-and-invisible-indexes
|
|
3
|
+
level: 2
|
|
4
|
+
course: mysql-query-optimization
|
|
5
|
+
type: output
|
|
6
|
+
description: "Master covering indexes and invisible indexes — use INCLUDE-like patterns and safely test index removal in MySQL 8.0+"
|
|
7
|
+
tags: [MySQL, covering-index, invisible-index, index-only-scan, intermediate]
|
|
8
|
+
|
|
9
|
+
state: {}
|
|
10
|
+
|
|
11
|
+
trigger: |
|
|
12
|
+
Your application's most frequent query runs 100K times per day and
|
|
13
|
+
takes 15ms on average. EXPLAIN shows it uses an index but still
|
|
14
|
+
reads the full row from the clustered index (type=ref, no "Using
|
|
15
|
+
index" in Extra). You want to make it an index-only scan.
|
|
16
|
+
|
|
17
|
+
The query:
|
|
18
|
+
SELECT customer_id, email, status
|
|
19
|
+
FROM users
|
|
20
|
+
WHERE status = 'active' AND country = 'US';
|
|
21
|
+
|
|
22
|
+
Current index: idx_status_country (status, country)
|
|
23
|
+
|
|
24
|
+
EXPLAIN:
|
|
25
|
+
type=ref, key=idx_status_country, rows=50000, Extra=NULL
|
|
26
|
+
|
|
27
|
+
The index matches the WHERE clause, so MySQL uses it to find the
|
|
28
|
+
50K matching row pointers. But then it must do 50K lookups into
|
|
29
|
+
the clustered index to retrieve customer_id and email — those
|
|
30
|
+
columns aren't in the secondary index.
|
|
31
|
+
|
|
32
|
+
Target: Make this a covering index (index-only scan) so MySQL
|
|
33
|
+
reads everything from the index without touching the table data.
|
|
34
|
+
|
|
35
|
+
Meanwhile, you also have 15 indexes on the users table and suspect
|
|
36
|
+
5 of them are unused. But dropping an index in production is scary
|
|
37
|
+
— what if an important query uses it at month-end?
|
|
38
|
+
|
|
39
|
+
MySQL 8.0 introduced invisible indexes:
|
|
40
|
+
ALTER TABLE users ALTER INDEX idx_old_column INVISIBLE;
|
|
41
|
+
-- The optimizer ignores this index, but it's still maintained
|
|
42
|
+
-- If something breaks, make it visible again instantly
|
|
43
|
+
|
|
44
|
+
Questions to address:
|
|
45
|
+
1. How to create a covering index for the query above?
|
|
46
|
+
2. Why doesn't MySQL have INCLUDE columns like PostgreSQL?
|
|
47
|
+
3. How do invisible indexes help safely remove unused indexes?
|
|
48
|
+
4. What's the trade-off of wider indexes for covering vs write perf?
|
|
49
|
+
5. How do you identify which indexes are unused?
|
|
50
|
+
|
|
51
|
+
Task: Design the covering index and the index cleanup strategy.
|
|
52
|
+
Write: the covering index for the query, how index-only scans work
|
|
53
|
+
in InnoDB, the invisible index workflow for safe index removal, how
|
|
54
|
+
to identify unused indexes (Performance Schema), and the trade-offs
|
|
55
|
+
of wider covering indexes.
|
|
56
|
+
|
|
57
|
+
assertions:
|
|
58
|
+
- type: llm_judge
|
|
59
|
+
criteria: "Covering index is correct — creates idx_status_country_email_custid(status, country, customer_id, email) or similar. Explains that 'Using index' in EXPLAIN Extra means all needed columns are in the index (index-only scan). MySQL doesn't have INCLUDE like PostgreSQL, so all columns must be part of the index key"
|
|
60
|
+
weight: 0.35
|
|
61
|
+
description: "Correct covering index"
|
|
62
|
+
- type: llm_judge
|
|
63
|
+
criteria: "Invisible index workflow is explained — make suspect index invisible, monitor for query regressions over a business cycle (1 week or 1 month), if no impact then drop it, if queries slow down make it visible again instantly. Uses performance_schema.table_io_waits_summary_by_index_usage or sys.schema_unused_indexes to find candidates"
|
|
64
|
+
weight: 0.35
|
|
65
|
+
description: "Invisible index workflow"
|
|
66
|
+
- type: llm_judge
|
|
67
|
+
criteria: "Trade-offs are analyzed — wider covering indexes use more storage and slow writes (more data to update per insert/update), but eliminate clustered index lookups for reads. Quantifies the trade-off: 50K lookups avoided per query execution vs additional index size and write overhead. Decision depends on read/write ratio"
|
|
68
|
+
weight: 0.30
|
|
69
|
+
description: "Trade-offs analyzed"
|