Claude Agent Skill · by Github

Sql Optimization

The sql-optimization skill provides comprehensive query tuning and database performance analysis for developers working with SQL databases including MySQL, Post

Install
Terminal · npx
$npx skills add https://github.com/github/awesome-copilot --skill sql-optimization
Works with Paperclip

How Sql Optimization fits into a Paperclip company.

Sql Optimization drops into any Paperclip agent that handles this kind of work. Assign it to a specialist inside a pre-configured PaperclipOrg company and the skill becomes available on every heartbeat — no prompt engineering, no tool wiring.

S
SaaS FactoryPaired

Pre-configured AI company — 18 agents, 18 skills, one-time purchase.

$27$59
Explore pack
Source file
SKILL.md296 lines
Expand
---name: sql-optimizationdescription: 'Universal SQL performance optimization assistant for comprehensive query tuning, indexing strategies, and database performance analysis across all SQL databases (MySQL, PostgreSQL, SQL Server, Oracle). Provides execution plan analysis, pagination optimization, batch operations, and performance monitoring guidance.'--- # SQL Performance Optimization Assistant Expert SQL performance optimization for ${selection} (or entire project if no selection). Focus on universal SQL optimization techniques that work across MySQL, PostgreSQL, SQL Server, Oracle, and other SQL databases. ## 🎯 Core Optimization Areas ### Query Performance Analysis```sql-- ❌ BAD: Inefficient query patternsSELECT * FROM orders oWHERE YEAR(o.created_at) = 2024  AND o.customer_id IN (      SELECT c.id FROM customers c WHERE c.status = 'active'  ); -- ✅ GOOD: Optimized query with proper indexing hintsSELECT o.id, o.customer_id, o.total_amount, o.created_atFROM orders oINNER JOIN customers c ON o.customer_id = c.idWHERE o.created_at >= '2024-01-01'   AND o.created_at < '2025-01-01'  AND c.status = 'active'; -- Required indexes:-- CREATE INDEX idx_orders_created_at ON orders(created_at);-- CREATE INDEX idx_customers_status ON customers(status);-- CREATE INDEX idx_orders_customer_id ON orders(customer_id);``` ### Index Strategy Optimization```sql-- ❌ BAD: Poor indexing strategyCREATE INDEX idx_user_data ON users(email, first_name, last_name, created_at); -- ✅ GOOD: Optimized composite indexing-- For queries filtering by email first, then sorting by created_atCREATE INDEX idx_users_email_created ON users(email, created_at); -- For full-text name searchesCREATE INDEX idx_users_name ON users(last_name, first_name); -- For user status queriesCREATE INDEX idx_users_status_created ON users(status, created_at)WHERE status IS NOT NULL;``` ### Subquery Optimization```sql-- ❌ BAD: Correlated subquerySELECT p.product_name, p.priceFROM products pWHERE p.price > (    SELECT AVG(price)     FROM products p2     WHERE p2.category_id = p.category_id); -- ✅ GOOD: Window function approachSELECT product_name, priceFROM (    SELECT product_name, price,           AVG(price) OVER (PARTITION BY category_id) as avg_category_price    FROM products) rankedWHERE price > avg_category_price;``` ## 📊 Performance Tuning Techniques ### JOIN Optimization```sql-- ❌ BAD: Inefficient JOIN order and conditionsSELECT o.*, c.name, p.product_nameFROM orders oLEFT JOIN customers c ON o.customer_id = c.idLEFT JOIN order_items oi ON o.id = oi.order_idLEFT JOIN products p ON oi.product_id = p.idWHERE o.created_at > '2024-01-01'  AND c.status = 'active'; -- ✅ GOOD: Optimized JOIN with filteringSELECT o.id, o.total_amount, c.name, p.product_nameFROM orders oINNER JOIN customers c ON o.customer_id = c.id AND c.status = 'active'INNER JOIN order_items oi ON o.id = oi.order_idINNER JOIN products p ON oi.product_id = p.idWHERE o.created_at > '2024-01-01';``` ### Pagination Optimization```sql-- ❌ BAD: OFFSET-based pagination (slow for large offsets)SELECT * FROM products ORDER BY created_at DESC LIMIT 20 OFFSET 10000; -- ✅ GOOD: Cursor-based paginationSELECT * FROM products WHERE created_at < '2024-06-15 10:30:00'ORDER BY created_at DESC LIMIT 20; -- Or using ID-based cursorSELECT * FROM products WHERE id > 1000ORDER BY id LIMIT 20;``` ### Aggregation Optimization```sql-- ❌ BAD: Multiple separate aggregation queriesSELECT COUNT(*) FROM orders WHERE status = 'pending';SELECT COUNT(*) FROM orders WHERE status = 'shipped';SELECT COUNT(*) FROM orders WHERE status = 'delivered'; -- ✅ GOOD: Single query with conditional aggregationSELECT     COUNT(CASE WHEN status = 'pending' THEN 1 END) as pending_count,    COUNT(CASE WHEN status = 'shipped' THEN 1 END) as shipped_count,    COUNT(CASE WHEN status = 'delivered' THEN 1 END) as delivered_countFROM orders;``` ## 🔍 Query Anti-Patterns ### SELECT Performance Issues```sql-- ❌ BAD: SELECT * anti-patternSELECT * FROM large_table ltJOIN another_table at ON lt.id = at.ref_id; -- ✅ GOOD: Explicit column selectionSELECT lt.id, lt.name, at.valueFROM large_table ltJOIN another_table at ON lt.id = at.ref_id;``` ### WHERE Clause Optimization```sql-- ❌ BAD: Function calls in WHERE clauseSELECT * FROM orders WHERE UPPER(customer_email) = 'JOHN@EXAMPLE.COM'; -- ✅ GOOD: Index-friendly WHERE clauseSELECT * FROM orders WHERE customer_email = 'john@example.com';-- Consider: CREATE INDEX idx_orders_email ON orders(LOWER(customer_email));``` ### OR vs UNION Optimization```sql-- ❌ BAD: Complex OR conditionsSELECT * FROM products WHERE (category = 'electronics' AND price < 1000)   OR (category = 'books' AND price < 50); -- ✅ GOOD: UNION approach for better optimizationSELECT * FROM products WHERE category = 'electronics' AND price < 1000UNION ALLSELECT * FROM products WHERE category = 'books' AND price < 50;``` ## 📈 Database-Agnostic Optimization ### Batch Operations```sql-- ❌ BAD: Row-by-row operationsINSERT INTO products (name, price) VALUES ('Product 1', 10.00);INSERT INTO products (name, price) VALUES ('Product 2', 15.00);INSERT INTO products (name, price) VALUES ('Product 3', 20.00); -- ✅ GOOD: Batch insertINSERT INTO products (name, price) VALUES ('Product 1', 10.00),('Product 2', 15.00),('Product 3', 20.00);``` ### Temporary Table Usage```sql-- ✅ GOOD: Using temporary tables for complex operationsCREATE TEMPORARY TABLE temp_calculations ASSELECT customer_id,        SUM(total_amount) as total_spent,       COUNT(*) as order_countFROM orders WHERE created_at >= '2024-01-01'GROUP BY customer_id; -- Use the temp table for further calculationsSELECT c.name, tc.total_spent, tc.order_countFROM temp_calculations tcJOIN customers c ON tc.customer_id = c.idWHERE tc.total_spent > 1000;``` ## 🛠️ Index Management ### Index Design Principles```sql-- ✅ GOOD: Covering index designCREATE INDEX idx_orders_covering ON orders(customer_id, created_at) INCLUDE (total_amount, status);  -- SQL Server syntax-- Or: CREATE INDEX idx_orders_covering ON orders(customer_id, created_at, total_amount, status); -- Other databases``` ### Partial Index Strategy```sql-- ✅ GOOD: Partial indexes for specific conditionsCREATE INDEX idx_orders_active ON orders(created_at) WHERE status IN ('pending', 'processing');``` ## 📊 Performance Monitoring Queries ### Query Performance Analysis```sql-- Generic approach to identify slow queries-- (Specific syntax varies by database) -- For MySQL:SELECT query_time, lock_time, rows_sent, rows_examined, sql_textFROM mysql.slow_logORDER BY query_time DESC; -- For PostgreSQL:SELECT query, calls, total_time, mean_timeFROM pg_stat_statementsORDER BY total_time DESC; -- For SQL Server:SELECT     qs.total_elapsed_time/qs.execution_count as avg_elapsed_time,    qs.execution_count,    SUBSTRING(qt.text, (qs.statement_start_offset/2)+1,        ((CASE qs.statement_end_offset WHEN -1 THEN DATALENGTH(qt.text)        ELSE qs.statement_end_offset END - qs.statement_start_offset)/2)+1) as query_textFROM sys.dm_exec_query_stats qsCROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) qtORDER BY avg_elapsed_time DESC;``` ## 🎯 Universal Optimization Checklist ### Query Structure- [ ] Avoiding SELECT * in production queries- [ ] Using appropriate JOIN types (INNER vs LEFT/RIGHT)- [ ] Filtering early in WHERE clauses- [ ] Using EXISTS instead of IN for subqueries when appropriate- [ ] Avoiding functions in WHERE clauses that prevent index usage ### Index Strategy- [ ] Creating indexes on frequently queried columns- [ ] Using composite indexes in the right column order- [ ] Avoiding over-indexing (impacts INSERT/UPDATE performance)- [ ] Using covering indexes where beneficial- [ ] Creating partial indexes for specific query patterns ### Data Types and Schema- [ ] Using appropriate data types for storage efficiency- [ ] Normalizing appropriately (3NF for OLTP, denormalized for OLAP)- [ ] Using constraints to help query optimizer- [ ] Partitioning large tables when appropriate ### Query Patterns- [ ] Using LIMIT/TOP for result set control- [ ] Implementing efficient pagination strategies- [ ] Using batch operations for bulk data changes- [ ] Avoiding N+1 query problems- [ ] Using prepared statements for repeated queries ### Performance Testing- [ ] Testing queries with realistic data volumes- [ ] Analyzing query execution plans- [ ] Monitoring query performance over time- [ ] Setting up alerts for slow queries- [ ] Regular index usage analysis ## 📝 Optimization Methodology 1. **Identify**: Use database-specific tools to find slow queries2. **Analyze**: Examine execution plans and identify bottlenecks3. **Optimize**: Apply appropriate optimization techniques4. **Test**: Verify performance improvements5. **Monitor**: Continuously track performance metrics6. **Iterate**: Regular performance review and optimization Focus on measurable performance improvements and always test optimizations with realistic data volumes and query patterns.