# Identifying Slow Queries

Slow queries can degrade the performance of your MySQL-based application, leading to lag, timeouts, or higher resource consumption. On Elestio, whether you’re accessing MySQL via terminal, inside a Docker Compose container, or using MySQL CLI tools, there are structured ways to inspect and optimize query performance. This guide covers how to analyze slow queries, interpret execution plans, and apply performance improvements using techniques like <span class="s3">EXPLAIN</span>, slow query logs, and schema analysis.

## **Analyzing Slow Queries from the Terminal**

When connected to a MySQL server from a terminal, you can use native SQL statements and built-in features to analyze the performance of specific queries. This is ideal for diagnosing issues in staging or production without needing container access.

#### **Connect to your MySQL instance via terminal**

To begin, log in to your MySQL server using the MySQL client:

```
mysql -u <username> -h <host> -p
```

You’ll be prompted for the password. Once inside, you can start analyzing queries.

#### **Use EXPLAIN to view the execution plan**

The <span class="s2">EXPLAIN</span> keyword shows how MySQL plans to execute a query. It breaks down how tables are accessed and joined, whether indexes are used, and how many rows are expected to be scanned.

```mysql
EXPLAIN SELECT * FROM orders WHERE customer_id = 42;
```

Review the <span class="s1">type</span>, <span class="s1">key</span>, <span class="s1">rows</span>, and <span class="s1">Extra</span> columns in the output. Look out for full table scans (<span class="s1">type = ALL</span>), which often signal that an index may be missing.

#### **Check current running queries**

To view which queries are actively running and their duration, use:

```mysql
SHOW FULL PROCESSLIST;
```

This can help identify long-running or stuck queries in real time.

## **Analyzing Inside Docker Compose**

If your MySQL service is running inside a Docker Compose setup (as Elestio uses), it may not be directly exposed on your host. In this case, analysis must be done from within the container.

#### **Access the MySQL container**

Open a shell inside your MySQL container using Docker Compose:

```
docker-compose exec mysql bash
```

This gives you a command-line shell inside the container.

#### **Connect to MySQL from inside the container**

Once inside the container, use the environment-defined credentials to access the database:

```
mysql -u $MYSQL_USER -p$MYSQL_PASSWORD $MYSQL_DATABASE
```

This gives you the same SQL interface as from the host terminal, enabling you to use <span class="s1">EXPLAIN</span>, <span class="s1">SHOW PROCESSLIST</span>, and performance schema tools.

#### **Enable and view the slow query log**

MySQL can log slow queries to a file. This must be enabled in your container’s `<span class="s1">my.cnf</span>` configuration file:

```
[mysqld]
slow_query_log = 1
slow_query_log_file = /var/log/mysql/slow.log
long_query_time = 1
```

After applying these settings, restart the container. Slow queries taking longer than <span class="s1">long\_query\_time</span> (in seconds) will be logged.

You can then inspect the log file:

```
cat /var/log/mysql/slow.log
```

## **Using Performance Schema** 

MySQL’s performance schema and built-in commands help track query statistics over time. This is useful when diagnosing repeat offenders or inefficient patterns.

#### **Enable the performance schema (if not already)**

Ensure <span class="s2">performance\_schema</span> is enabled in your MySQL configuration:

```
[mysqld]
performance_schema=ON
```

Restart the container after updating the config.

#### **Identify top queries using statement summaries**

This SQL query shows which SQL statements have the longest average execution times:

```mysql
SELECT digest_text, count_star, avg_timer_wait/1000000000000 AS avg_time_sec
FROM performance_schema.events_statements_summary_by_digest
ORDER BY avg_timer_wait DESC
LIMIT 10;
```

This helps you find the most resource-intensive queries over time.

## **Understanding the MySQL Execution Plan**

Reading the output of <span class="s2">EXPLAIN</span> is essential to understand how MySQL processes your query and whether it is using indexes efficiently.

Key output fields to interpret:

- **<span class="s1">type</span>**: The join type. Prefer <span class="s1">ref</span>, <span class="s1">range</span>, or <span class="s1">const</span> over <span class="s1">ALL</span> (which indicates a full table scan).
- **<span class="s1">key</span>**: The index used for the query. A <span class="s1">NULL</span> value may indicate a missing index.
- **<span class="s1">rows</span>**: Estimated number of rows MySQL will scan. Lower is better.
- **<span class="s1">Extra</span>**: Look for warnings like <span class="s1">Using temporary</span> or <span class="s1">Using filesort</span>, which may suggest suboptimal queries.

Use `<span class="s2">EXPLAIN ANALYZE</span>` (available in MySQL 8.0+) to see actual vs. estimated performance:

```mysql
EXPLAIN ANALYZE SELECT * FROM orders WHERE customer_id = 42;
```

## **Optimizing Queries for Better Performance**

Once you’ve identified inefficient queries, optimization involves rewriting queries, adding indexes, or adjusting the schema.

Common techniques:

- <span class="s1">**Add indexes**</span> to columns frequently used in <span class="s2">WHERE</span>, <span class="s2">JOIN</span>, and <span class="s2">ORDER BY</span>.
- **Avoid SELECT\*** : Only fetch columns you need to reduce I/O.
- <span class="s1">**Use LIMIT**</span> when fetching preview data or paginated results.
- <span class="s1">**Re-write joins or subqueries**</span> to reduce temporary tables and filesort operations.
- **Update statistics**<span class="s1"> with </span><span class="s2">ANALYZE TABLE</span><span class="s1">:</span>

```mysql
ANALYZE TABLE orders;
```