Cassandra Slow Queries
Slow queries manifest as high latency, timeouts, or degraded application performance. This playbook helps identify and resolve query performance issues.
Symptoms
Section titled “Symptoms”- High read/write latencies in
nodetool proxyhistograms - Query timeouts from client applications
- Specific queries consistently slow
- “Slow query” warnings in logs
- User-reported application slowness
Diagnosis
Section titled “Diagnosis”Step 1: Check Overall Latencies
Section titled “Step 1: Check Overall Latencies”# Coordinator latenciesnodetool proxyhistograms
# Per-table latenciesnodetool tablehistograms my_keyspace my_tableWhat to look for:
- p99 latency > 100ms for reads
- p99 latency > 50ms for writes
- Large gap between p50 and p99 (inconsistent performance)
Step 2: Enable Slow Query Logging
Section titled “Step 2: Enable Slow Query Logging”slow_query_log_timeout_in_ms: 500Then check logs:
grep "slow query" /var/log/cassandra/debug.log | tail -50Step 3: Trace Specific Queries
Section titled “Step 3: Trace Specific Queries”TRACING ON;SELECT * FROM my_table WHERE ...;TRACING OFF;What to look for in trace:
- Time spent in each phase
- Number of SSTables read
- Tombstones scanned
- Partitions touched
Step 4: Check Table Health
Section titled “Step 4: Check Table Health”nodetool tablestats my_keyspace.my_tableProblem indicators:
- High SSTable count (> 20)
- High tombstones per slice
- Large partition sizes
- Low key cache hit rate
Step 5: Check for Hotspots
Section titled “Step 5: Check for Hotspots”# Top partitions by read/write activitynodetool toppartitions my_keyspace my_table 10000Resolution
Section titled “Resolution”Query Anti-Pattern: Full Table Scan
Section titled “Query Anti-Pattern: Full Table Scan”Problem:
SELECT * FROM users; -- Scans entire clusterSolution:
-- Add WHERE clause on partition keySELECT * FROM users WHERE user_id = ?;
-- Or use paginationSELECT * FROM users LIMIT 100;Query Anti-Pattern: ALLOW FILTERING
Section titled “Query Anti-Pattern: ALLOW FILTERING”Problem:
SELECT * FROM users WHERE email = 'test@example.com' ALLOW FILTERING;Solution:
-- Create secondary indexCREATE INDEX ON users (email);
-- Or create materialized viewCREATE MATERIALIZED VIEW users_by_email AS SELECT * FROM users WHERE email IS NOT NULL AND user_id IS NOT NULL PRIMARY KEY (email, user_id);Query Anti-Pattern: IN with Many Values
Section titled “Query Anti-Pattern: IN with Many Values”Problem:
SELECT * FROM orders WHERE order_id IN (uuid1, uuid2, ..., uuid100);Solution:
-- Use async parallel queries from application-- Or batch into smaller groupsSELECT * FROM orders WHERE order_id IN (uuid1, uuid2, uuid3);Query Anti-Pattern: Range Queries on Clustering Columns
Section titled “Query Anti-Pattern: Range Queries on Clustering Columns”Problem:
SELECT * FROM events WHERE user_id = ? AND event_time > '2024-01-01';-- Scans potentially millions of rowsSolution:
-- Add LIMITSELECT * FROM events WHERE user_id = ? AND event_time > '2024-01-01' LIMIT 1000;
-- Or redesign for bounded queriesSELECT * FROM events WHERE user_id = ? AND day = '2024-01-15';Data Model Issue: Large Partitions
Section titled “Data Model Issue: Large Partitions”# Check partition sizesnodetool tablestats my_keyspace.my_table | grep partitionData Model Issue: Tombstone Accumulation
Section titled “Data Model Issue: Tombstone Accumulation”# Check tombstone countsnodetool tablestats my_keyspace.my_table | grep tombstoneInfrastructure Issue: Compaction Backlog
Section titled “Infrastructure Issue: Compaction Backlog”# Check pending compactionsnodetool compactionstats
# If backlog existsnodetool compact my_keyspace my_tableInfrastructure Issue: Insufficient Resources
Section titled “Infrastructure Issue: Insufficient Resources”# Check CPUtop -p $(pgrep -f CassandraDaemon)
# Check disk I/Oiostat -x 1 5
# Check thread poolsnodetool tpstatsQuery Optimization Checklist
Section titled “Query Optimization Checklist”| Check | Good | Bad | Fix |
|---|---|---|---|
| Partition key in WHERE | Yes | No | Add partition key filter |
| ALLOW FILTERING | Not used | Used | Create index or view |
| IN clause size | < 10 values | > 100 values | Parallel queries |
| Result set size | LIMIT used | No LIMIT | Add LIMIT |
| Table SSTable count | < 20 | > 50 | Run compaction |
| Tombstones per read | < 100 | > 1000 | Fix data model |
| Key cache hit rate | > 90% | < 50% | Increase cache |
Recovery
Section titled “Recovery”Verify Improvement
Section titled “Verify Improvement”# Check latencies after fixnodetool tablehistograms my_keyspace my_table
# Trace query againTRACING ON;<your query>;TRACING OFF;Monitor Going Forward
Section titled “Monitor Going Forward”Set up alerts on:
- p99 read latency > 100ms
- p99 write latency > 50ms
- Slow query log entries
Prevention
Section titled “Prevention”- Review queries before production - Check execution plans
- Monitor query latencies - Alert on degradation
- Design data model for queries - Don’t retrofit
- Use prepared statements - Reduce parsing overhead
- Implement client-side caching - Reduce load for hot data
- Run regular compaction - Keep SSTable counts low
Related Commands
Section titled “Related Commands”| Command | Purpose |
|---|---|
nodetool proxyhistograms | Overall latencies |
nodetool tablehistograms | Per-table latencies |
nodetool tablestats | Table health metrics |
nodetool toppartitions | Identify hot partitions |
TRACING ON/OFF | Query tracing |
Related Documentation
Section titled “Related Documentation”- CQL Reference - Query syntax and options
- Data Modeling - Design patterns
- Large Partition Issues - Partition sizing
- Tombstone Accumulation - Tombstone issues