You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
fix(seed): run workload queries as standalone SQL for pg_stat_statements
pg_stat_statements only tracks individual SQL statements, not:
- Queries inside DO $$ PL/pgSQL blocks
- LATERAL subqueries (tracked as part of outer query)
Changed from LATERAL+generate_series approach to generating a SQL file
with repeated individual SELECT statements that psql executes separately.
Each statement is tracked by pg_stat_statements and aggregated under its
queryid with cumulative calls and total_exec_time.
This should populate the Performance tab with real slow queries from the
300K+ audit_log and 100K+ order_items tables.
Co-authored-by: Venkat SF <venkatesh.sakamuri@stayflexi.com>
SELECT 'correlated subquery pattern' as pattern, COUNT(*)
415
-
FROM generate_series(1, 20) g,
416
-
LATERAL (
417
-
SELECT COUNT(*) FROM orders o
418
-
WHERE EXISTS (SELECT 1 FROM audit_log a WHERE a.record_id = o.id AND a.table_name = 'orders' AND a.action = 'UPDATE')
419
-
) sub;
420
-
421
-
SELECT 'Workload patterns completed' as status;
422
-
EOWORK
423
-
424
-
echo" Workload patterns completed."
360
+
echo" Starting workload (this takes about 60-90 seconds)..."
361
+
362
+
# CRITICAL: pg_stat_statements only tracks STANDALONE SQL statements.
363
+
# - Queries inside DO $$ PL/pgSQL blocks are NOT tracked
364
+
# - LATERAL subqueries are tracked as part of the outer query, not separately
365
+
# - Each SELECT must be a separate statement sent to psql
366
+
#
367
+
# We generate a SQL file with repeated individual statements and pipe to psql.
368
+
# Each statement is tracked separately, and identical statements aggregate
369
+
# under the same queryid with cumulative calls and total_exec_time.
370
+
371
+
workload_sql="$(mktemp)"
372
+
cat >"$workload_sql"<<'EOSQL'
373
+
-- Pattern 1: LOWER() on status column defeats index
374
+
-- This is intentionally inefficient - LOWER() prevents index use
375
+
SELECT COUNT(*) FROM orders WHERE LOWER(status) = 'delivered' AND total_amount > 100;
376
+
SELECT COUNT(*) FROM orders WHERE LOWER(status) = 'delivered' AND total_amount > 100;
377
+
SELECT COUNT(*) FROM orders WHERE LOWER(status) = 'delivered' AND total_amount > 100;
378
+
SELECT COUNT(*) FROM orders WHERE LOWER(status) = 'delivered' AND total_amount > 100;
379
+
SELECT COUNT(*) FROM orders WHERE LOWER(status) = 'delivered' AND total_amount > 100;
380
+
SELECT COUNT(*) FROM orders WHERE LOWER(status) = 'delivered' AND total_amount > 100;
381
+
SELECT COUNT(*) FROM orders WHERE LOWER(status) = 'delivered' AND total_amount > 100;
382
+
SELECT COUNT(*) FROM orders WHERE LOWER(status) = 'delivered' AND total_amount > 100;
383
+
SELECT COUNT(*) FROM orders WHERE LOWER(status) = 'delivered' AND total_amount > 100;
384
+
SELECT COUNT(*) FROM orders WHERE LOWER(status) = 'delivered' AND total_amount > 100;
385
+
386
+
-- Pattern 2: Full table scan on audit_log (300K+ rows)
387
+
SELECT COUNT(*) FROM audit_log WHERE table_name = 'orders' AND changed_at > NOW() - INTERVAL '90 days';
388
+
SELECT COUNT(*) FROM audit_log WHERE table_name = 'orders' AND changed_at > NOW() - INTERVAL '90 days';
389
+
SELECT COUNT(*) FROM audit_log WHERE table_name = 'orders' AND changed_at > NOW() - INTERVAL '90 days';
390
+
SELECT COUNT(*) FROM audit_log WHERE table_name = 'orders' AND changed_at > NOW() - INTERVAL '90 days';
391
+
SELECT COUNT(*) FROM audit_log WHERE table_name = 'orders' AND changed_at > NOW() - INTERVAL '90 days';
392
+
SELECT COUNT(*) FROM audit_log WHERE table_name = 'orders' AND changed_at > NOW() - INTERVAL '90 days';
393
+
SELECT COUNT(*) FROM audit_log WHERE table_name = 'orders' AND changed_at > NOW() - INTERVAL '90 days';
394
+
SELECT COUNT(*) FROM audit_log WHERE table_name = 'orders' AND changed_at > NOW() - INTERVAL '90 days';
395
+
SELECT COUNT(*) FROM audit_log WHERE table_name = 'orders' AND changed_at > NOW() - INTERVAL '90 days';
396
+
SELECT COUNT(*) FROM audit_log WHERE table_name = 'orders' AND changed_at > NOW() - INTERVAL '90 days';
397
+
398
+
-- Pattern 3: Sort on audit_log without index on changed_at
399
+
SELECT id FROM audit_log WHERE table_name IN ('orders', 'customers', 'products') ORDER BY changed_at DESC LIMIT 1000;
400
+
SELECT id FROM audit_log WHERE table_name IN ('orders', 'customers', 'products') ORDER BY changed_at DESC LIMIT 1000;
401
+
SELECT id FROM audit_log WHERE table_name IN ('orders', 'customers', 'products') ORDER BY changed_at DESC LIMIT 1000;
402
+
SELECT id FROM audit_log WHERE table_name IN ('orders', 'customers', 'products') ORDER BY changed_at DESC LIMIT 1000;
403
+
SELECT id FROM audit_log WHERE table_name IN ('orders', 'customers', 'products') ORDER BY changed_at DESC LIMIT 1000;
404
+
SELECT id FROM audit_log WHERE table_name IN ('orders', 'customers', 'products') ORDER BY changed_at DESC LIMIT 1000;
405
+
SELECT id FROM audit_log WHERE table_name IN ('orders', 'customers', 'products') ORDER BY changed_at DESC LIMIT 1000;
406
+
SELECT id FROM audit_log WHERE table_name IN ('orders', 'customers', 'products') ORDER BY changed_at DESC LIMIT 1000;
407
+
SELECT id FROM audit_log WHERE table_name IN ('orders', 'customers', 'products') ORDER BY changed_at DESC LIMIT 1000;
408
+
SELECT id FROM audit_log WHERE table_name IN ('orders', 'customers', 'products') ORDER BY changed_at DESC LIMIT 1000;
409
+
410
+
-- Pattern 4: ILIKE with leading wildcard - cannot use index
411
+
SELECT COUNT(*) FROM products WHERE name ILIKE '%widget%' OR description ILIKE '%premium%';
412
+
SELECT COUNT(*) FROM products WHERE name ILIKE '%widget%' OR description ILIKE '%premium%';
413
+
SELECT COUNT(*) FROM products WHERE name ILIKE '%widget%' OR description ILIKE '%premium%';
414
+
SELECT COUNT(*) FROM products WHERE name ILIKE '%widget%' OR description ILIKE '%premium%';
415
+
SELECT COUNT(*) FROM products WHERE name ILIKE '%widget%' OR description ILIKE '%premium%';
416
+
SELECT COUNT(*) FROM products WHERE name ILIKE '%widget%' OR description ILIKE '%premium%';
417
+
SELECT COUNT(*) FROM products WHERE name ILIKE '%widget%' OR description ILIKE '%premium%';
418
+
SELECT COUNT(*) FROM products WHERE name ILIKE '%widget%' OR description ILIKE '%premium%';
419
+
SELECT COUNT(*) FROM products WHERE name ILIKE '%widget%' OR description ILIKE '%premium%';
420
+
SELECT COUNT(*) FROM products WHERE name ILIKE '%widget%' OR description ILIKE '%premium%';
421
+
422
+
-- Pattern 5: Large join order_items (100K) to orders (5K)
423
+
SELECT COUNT(*), SUM(oi.subtotal) FROM order_items oi JOIN orders o ON oi.order_id = o.id WHERE o.status = 'delivered';
424
+
SELECT COUNT(*), SUM(oi.subtotal) FROM order_items oi JOIN orders o ON oi.order_id = o.id WHERE o.status = 'delivered';
425
+
SELECT COUNT(*), SUM(oi.subtotal) FROM order_items oi JOIN orders o ON oi.order_id = o.id WHERE o.status = 'delivered';
426
+
SELECT COUNT(*), SUM(oi.subtotal) FROM order_items oi JOIN orders o ON oi.order_id = o.id WHERE o.status = 'delivered';
427
+
SELECT COUNT(*), SUM(oi.subtotal) FROM order_items oi JOIN orders o ON oi.order_id = o.id WHERE o.status = 'delivered';
428
+
SELECT COUNT(*), SUM(oi.subtotal) FROM order_items oi JOIN orders o ON oi.order_id = o.id WHERE o.status = 'delivered';
429
+
SELECT COUNT(*), SUM(oi.subtotal) FROM order_items oi JOIN orders o ON oi.order_id = o.id WHERE o.status = 'delivered';
430
+
SELECT COUNT(*), SUM(oi.subtotal) FROM order_items oi JOIN orders o ON oi.order_id = o.id WHERE o.status = 'delivered';
431
+
SELECT COUNT(*), SUM(oi.subtotal) FROM order_items oi JOIN orders o ON oi.order_id = o.id WHERE o.status = 'delivered';
432
+
SELECT COUNT(*), SUM(oi.subtotal) FROM order_items oi JOIN orders o ON oi.order_id = o.id WHERE o.status = 'delivered';
433
+
434
+
-- Pattern 6: Expensive aggregation with GROUP BY across large tables
435
+
SELECT DATE_TRUNC('month', o.created_at), p.name, COUNT(*), SUM(oi.subtotal) FROM orders o JOIN order_items oi ON o.id = oi.order_id JOIN products p ON oi.product_id = p.id WHERE o.status NOT IN ('cancelled', 'refunded') GROUP BY 1, p.id, p.name ORDER BY 4 DESC LIMIT 100;
436
+
SELECT DATE_TRUNC('month', o.created_at), p.name, COUNT(*), SUM(oi.subtotal) FROM orders o JOIN order_items oi ON o.id = oi.order_id JOIN products p ON oi.product_id = p.id WHERE o.status NOT IN ('cancelled', 'refunded') GROUP BY 1, p.id, p.name ORDER BY 4 DESC LIMIT 100;
437
+
SELECT DATE_TRUNC('month', o.created_at), p.name, COUNT(*), SUM(oi.subtotal) FROM orders o JOIN order_items oi ON o.id = oi.order_id JOIN products p ON oi.product_id = p.id WHERE o.status NOT IN ('cancelled', 'refunded') GROUP BY 1, p.id, p.name ORDER BY 4 DESC LIMIT 100;
438
+
SELECT DATE_TRUNC('month', o.created_at), p.name, COUNT(*), SUM(oi.subtotal) FROM orders o JOIN order_items oi ON o.id = oi.order_id JOIN products p ON oi.product_id = p.id WHERE o.status NOT IN ('cancelled', 'refunded') GROUP BY 1, p.id, p.name ORDER BY 4 DESC LIMIT 100;
439
+
SELECT DATE_TRUNC('month', o.created_at), p.name, COUNT(*), SUM(oi.subtotal) FROM orders o JOIN order_items oi ON o.id = oi.order_id JOIN products p ON oi.product_id = p.id WHERE o.status NOT IN ('cancelled', 'refunded') GROUP BY 1, p.id, p.name ORDER BY 4 DESC LIMIT 100;
440
+
SELECT DATE_TRUNC('month', o.created_at), p.name, COUNT(*), SUM(oi.subtotal) FROM orders o JOIN order_items oi ON o.id = oi.order_id JOIN products p ON oi.product_id = p.id WHERE o.status NOT IN ('cancelled', 'refunded') GROUP BY 1, p.id, p.name ORDER BY 4 DESC LIMIT 100;
441
+
SELECT DATE_TRUNC('month', o.created_at), p.name, COUNT(*), SUM(oi.subtotal) FROM orders o JOIN order_items oi ON o.id = oi.order_id JOIN products p ON oi.product_id = p.id WHERE o.status NOT IN ('cancelled', 'refunded') GROUP BY 1, p.id, p.name ORDER BY 4 DESC LIMIT 100;
442
+
SELECT DATE_TRUNC('month', o.created_at), p.name, COUNT(*), SUM(oi.subtotal) FROM orders o JOIN order_items oi ON o.id = oi.order_id JOIN products p ON oi.product_id = p.id WHERE o.status NOT IN ('cancelled', 'refunded') GROUP BY 1, p.id, p.name ORDER BY 4 DESC LIMIT 100;
443
+
SELECT DATE_TRUNC('month', o.created_at), p.name, COUNT(*), SUM(oi.subtotal) FROM orders o JOIN order_items oi ON o.id = oi.order_id JOIN products p ON oi.product_id = p.id WHERE o.status NOT IN ('cancelled', 'refunded') GROUP BY 1, p.id, p.name ORDER BY 4 DESC LIMIT 100;
444
+
SELECT DATE_TRUNC('month', o.created_at), p.name, COUNT(*), SUM(oi.subtotal) FROM orders o JOIN order_items oi ON o.id = oi.order_id JOIN products p ON oi.product_id = p.id WHERE o.status NOT IN ('cancelled', 'refunded') GROUP BY 1, p.id, p.name ORDER BY 4 DESC LIMIT 100;
445
+
446
+
-- Pattern 7: Missing composite index on (status, payment_status)
447
+
SELECT COUNT(*) FROM orders WHERE status = 'pending' AND payment_status = 'paid' AND created_at > NOW() - INTERVAL '30 days';
448
+
SELECT COUNT(*) FROM orders WHERE status = 'pending' AND payment_status = 'paid' AND created_at > NOW() - INTERVAL '30 days';
449
+
SELECT COUNT(*) FROM orders WHERE status = 'pending' AND payment_status = 'paid' AND created_at > NOW() - INTERVAL '30 days';
450
+
SELECT COUNT(*) FROM orders WHERE status = 'pending' AND payment_status = 'paid' AND created_at > NOW() - INTERVAL '30 days';
451
+
SELECT COUNT(*) FROM orders WHERE status = 'pending' AND payment_status = 'paid' AND created_at > NOW() - INTERVAL '30 days';
452
+
SELECT COUNT(*) FROM orders WHERE status = 'pending' AND payment_status = 'paid' AND created_at > NOW() - INTERVAL '30 days';
453
+
SELECT COUNT(*) FROM orders WHERE status = 'pending' AND payment_status = 'paid' AND created_at > NOW() - INTERVAL '30 days';
454
+
SELECT COUNT(*) FROM orders WHERE status = 'pending' AND payment_status = 'paid' AND created_at > NOW() - INTERVAL '30 days';
455
+
SELECT COUNT(*) FROM orders WHERE status = 'pending' AND payment_status = 'paid' AND created_at > NOW() - INTERVAL '30 days';
456
+
SELECT COUNT(*) FROM orders WHERE status = 'pending' AND payment_status = 'paid' AND created_at > NOW() - INTERVAL '30 days';
457
+
458
+
-- Pattern 8: Correlated subquery - inefficient EXISTS on audit_log
459
+
SELECT COUNT(*) FROM orders o WHERE EXISTS (SELECT 1 FROM audit_log a WHERE a.record_id = o.id AND a.table_name = 'orders' AND a.action = 'UPDATE');
460
+
SELECT COUNT(*) FROM orders o WHERE EXISTS (SELECT 1 FROM audit_log a WHERE a.record_id = o.id AND a.table_name = 'orders' AND a.action = 'UPDATE');
461
+
SELECT COUNT(*) FROM orders o WHERE EXISTS (SELECT 1 FROM audit_log a WHERE a.record_id = o.id AND a.table_name = 'orders' AND a.action = 'UPDATE');
462
+
SELECT COUNT(*) FROM orders o WHERE EXISTS (SELECT 1 FROM audit_log a WHERE a.record_id = o.id AND a.table_name = 'orders' AND a.action = 'UPDATE');
463
+
SELECT COUNT(*) FROM orders o WHERE EXISTS (SELECT 1 FROM audit_log a WHERE a.record_id = o.id AND a.table_name = 'orders' AND a.action = 'UPDATE');
464
+
SELECT COUNT(*) FROM orders o WHERE EXISTS (SELECT 1 FROM audit_log a WHERE a.record_id = o.id AND a.table_name = 'orders' AND a.action = 'UPDATE');
465
+
SELECT COUNT(*) FROM orders o WHERE EXISTS (SELECT 1 FROM audit_log a WHERE a.record_id = o.id AND a.table_name = 'orders' AND a.action = 'UPDATE');
466
+
SELECT COUNT(*) FROM orders o WHERE EXISTS (SELECT 1 FROM audit_log a WHERE a.record_id = o.id AND a.table_name = 'orders' AND a.action = 'UPDATE');
467
+
SELECT COUNT(*) FROM orders o WHERE EXISTS (SELECT 1 FROM audit_log a WHERE a.record_id = o.id AND a.table_name = 'orders' AND a.action = 'UPDATE');
468
+
SELECT COUNT(*) FROM orders o WHERE EXISTS (SELECT 1 FROM audit_log a WHERE a.record_id = o.id AND a.table_name = 'orders' AND a.action = 'UPDATE');
0 commit comments