1. Enabling the Slow Query Log in MariaDB
The slow query log can be enabled dynamically or via the configuration file (my.cnf). Below are both approaches.
Example 1: Enable Slow Query Log Dynamically
To enable the slow query log without restarting MariaDB:
SET GLOBAL slow_query_log = 'ON';
SET GLOBAL long_query_time = 1; -- Log queries taking >1 second
SET GLOBAL slow_query_log_file = '/var/log/mysql/slow-query.log';
SET GLOBAL log_queries_not_using_indexes = 'ON'; -- Log queries not using indexes
- Verification:
SHOW VARIABLES LIKE 'slow_query_log%';
SHOW VARIABLES LIKE 'long_query_time';
Expected output:
+------------------------+----------------+
| Variable_name | Value |
+------------------------+----------------+
| slow_query_log | ON |
| slow_query_log_file | /var/log/mysql/slow-query.log |
+------------------------+----------------+
+-----------------+-------+
| Variable_name | Value |
+-----------------+-------+
| long_query_time | 1.000 |
+-----------------+-------+
Example 2: Enable Slow Query Log in Configuration File
Edit the MariaDB configuration file (e.g., /etc/my.cnf or /etc/mysql/mariadb.conf.d/50-server.cnf):
[mysqld]
slow_query_log = 1
slow_query_log_file = /var/log/mysql/slow-query.log
long_query_time = 1
log_queries_not_using_indexes = 1
log_output = FILE -- Log to file (alternatively, TABLE for mysql.slow_log)
- Apply Changes:
Restart MariaDB:
sudo systemctl restart mariadb
- Ensure Log File Permissions:
sudo touch /var/log/mysql/slow-query.log
sudo chown mysql:mysql /var/log/mysql/slow-query.log
sudo chmod 640 /var/log/mysql/slow-query.log
2. Example Slow Query Log Output
Once enabled, slow queries are logged to the specified file (e.g., /var/log/mysql/slow-query.log). Below is an example of a slow query log entry:
/usr/sbin/mysqld, Version: 10.5.15-MariaDB (MariaDB Server). started with:
Tcp port: 3306 Unix socket: /var/run/mysqld/mysqld.sock
Time Id Command Argument
# Time: 2025-05-20T14:30:45.123456Z
# User@Host: app_user[app_user] @ localhost []
# Query_time: 1.234567 Lock_time: 0.000123 Rows_sent: 1000 Rows_examined: 100000
SET timestamp=1742581845;
SELECT * FROM large_table WHERE name = 'example';
- Explanation:
- Query_time: 1.234567 seconds (the query took ~1.23 seconds).
- Lock_time: Time spent acquiring locks (0.000123 seconds).
- Rows_sent: 1000 rows returned to the client.
- Rows_examined: 100,000 rows scanned (indicates potential inefficiency).
- Query: The actual SQL statement (
SELECT * FROM large_table WHERE name = 'example').
3. Analyzing Slow Queries with mysqldumpslow
MariaDB includes mysqldumpslow, a tool to summarize and analyze slow query logs.
Example 3: Using mysqldumpslow
Run mysqldumpslow to aggregate slow query data:
mysqldumpslow /var/log/mysql/slow-query.log
- Sample Output:
Count: 10 Time=1.25s (12.5s) Lock=0.00s (0.00s) Rows=1000.0 (10000), app_user[app_user]@localhost
SELECT * FROM large_table WHERE name = 'example'
- Count: Query appeared 10 times.
- Time: Average execution time (1.25s per query, 12.5s total).
- Rows: Average rows returned (1000 per query).
- Filter Specific Queries:
To focus on queries with high execution time:
mysqldumpslow -t 5 -s t /var/log/mysql/slow-query.log
-t 5: Show top 5 queries.-s t: Sort by total time.
4. Logging to a Table for Query Analysis
Instead of a file, you can log slow queries to the mysql.slow_log table for easier querying.
Example 4: Enable Table-Based Logging
SET GLOBAL log_output = 'TABLE';
SET GLOBAL slow_query_log = 'ON';
SET GLOBAL long_query_time = 1;
- Query the Slow Log Table:
SELECT start_time, user_host, query_time, lock_time, rows_sent, rows_examined, sql_text
FROM mysql.slow_log
WHERE query_time > 1
ORDER BY query_time DESC
LIMIT 5;
- Sample Output:
+---------------------+-----------+-------------+-----------+-----------+---------------+----------------------------------+
| start_time | user_host | query_time | lock_time | rows_sent | rows_examined | sql_text |
+---------------------+-----------+-------------+-----------+-----------+---------------+----------------------------------+
| 2025-05-20 14:30:45 | app_user | 00:00:01.23 | 00:00:00.00 | 1000 | 100000 | SELECT * FROM large_table WHERE name = 'example' |
+---------------------+-----------+-------------+-----------+-----------+---------------+----------------------------------+
5. Optimizing a Slow Query
Suppose the slow query is:
SELECT * FROM large_table WHERE name = 'example';
- Step 1: Analyze with
EXPLAIN:
EXPLAIN SELECT * FROM large_table WHERE name = 'example';
- Sample Output:
+----+-------------+------------+------+---------------+------+---------+------+--------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+------------+------+---------------+------+---------+------+--------+-------------+
| 1 | SIMPLE | large_table| ALL | NULL | NULL | NULL | NULL | 100000 | Using where |
+----+-------------+------------+------+---------------+------+---------+------+--------+-------------+
- Issue:
type: ALLindicates a full table scan, and no index is used (key: NULL).
- Step 2: Create an Index:
CREATE INDEX idx_name ON large_table(name);
- Step 3: Re-run
EXPLAIN:
EXPLAIN SELECT * FROM large_table WHERE name = 'example';
- Improved Output:
+----+-------------+------------+------+---------------+----------+---------+-------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+------------+------+---------------+----------+---------+-------+------+-------------+
| 1 | SIMPLE | large_table| ref | idx_name | idx_name | 256 | const | 1 | Using where |
+----+-------------+------------+------+---------------+----------+---------+-------+------+-------------+
- Improvement:
type: refandrows: 1indicate the index is used, reducing scanned rows.
- Step 4: Verify Performance:
Run the query and check the slow query log again. If the query time drops below long_query_time, it won’t appear in the log.
6. Advanced Configuration: Logging Query Plans
To include query execution plans in the slow query log (similar to PostgreSQL’s auto_explain):
SET GLOBAL log_slow_verbosity = 'query_plan,explain';
- Example Log Entry with Query Plan:
# Time: 2025-05-20T14:32:00.123456Z
# User@Host: app_user[app_user] @ localhost []
# Query_time: 1.500000 Lock_time: 0.000100 Rows_sent: 1000 Rows_examined: 100000
# EXPLAIN: id select_type table type possible_keys key key_len ref rows Extra
# EXPLAIN: 1 SIMPLE large_table ALL NULL NULL NULL NULL 100000 Using where
SET timestamp=1742581920;
SELECT * FROM large_table WHERE name = 'example';
- Use Case: Helps identify why a query is slow (e.g., full table scans, missing indexes).
7. Automating Analysis with a Script
To regularly analyze slow queries, you can use a script to parse the log file or table.
Example 5: Bash Script to Summarize Slow Queries
#!/bin/bash
LOG_FILE="/var/log/mysql/slow-query.log"
mysqldumpslow -t 10 -s t "$LOG_FILE" > /tmp/slow_query_summary.txt
cat /tmp/slow_query_summary.txt
- Save as
analyze_slow_queries.sh, make executable (chmod +x), and run:
./analyze_slow_queries.sh
Example 6: SQL Query for Table-Based Log Analysis
If using log_output = TABLE:
SELECT sql_text, COUNT(*) as query_count, AVG(query_time) as avg_time, SUM(rows_examined) as total_rows
FROM mysql.slow_log
GROUP BY sql_text
ORDER BY avg_time DESC
LIMIT 5;
Notes
- Log Rotation: Use
logrotateto manage slow query log file size:
/var/log/mysql/slow-query.log {
weekly
rotate 4
compress
missingok
notifempty
}
- Performance Impact: Enabling
log_queries_not_using_indexesorlog_slow_verbosity = 'query_plan'may increase logging overhead. Test in a non-production environment first. - Tools: Use
Percona Toolkit(pt-query-digest) for advanced slow query analysis:
pt-query-digest /var/log/mysql/slow-query.log
For further details, see the [MariaDB documentation](https://mariadb.com/kb/en/slow-query-log-overview/). If you need help with specific queries or tools, let me know!
[file-name 000142_2025-05-20_14-56-07.txt]