For the query above, the following recommendations will be helpful as part of the SQL tuning process.
You'll find 3 sections below:
The optimization process and recommendations:
- Avoid Subqueries (query line: 17): We advise against using subqueries as they are not optimized well by the optimizer. Therefore, it's recommended to join a newly created temporary table that holds the data, which also includes the relevant search index.
- Create Optimal Indexes (modified query below): The recommended indexes are an integral part of this optimization effort and should be created before testing the execution duration of the optimized query.
- Sort and Limit Before Joining (modified query below): In cases where the joins aren't filtering any rows, it's possible to sort and limit the amount of rows using a subquery in the FROM clause, before applying the joins to all other tables.
- Use Equality Operator Over LIKE (modified query below): Equality operators (such as '\u003d') are usually better optimized and more readable. Prefer the equality operator when searching for a constant value such as `34`.
- Use Equality Operator Over LIKE (modified query below): Equality operators (such as '\u003d') are usually better optimized and more readable. Prefer the equality operator when searching for a constant value such as `35`.
- Use Numeric Column Types For Numeric Values (query line: 36): Referencing a numeric value (e.g. 34) as a string in a WHERE clause might result in poor performance. Possible impacts of storing numbers as varchars: more space will be used, you won't be able to perform arithmetic operations, the data won't be self-validated, aggregation functions like SUM won't work, the output may sort incorrectly and more. If the column is numeric, remove the quotes from the constant value, to make sure a numeric comparison is done.
- Use Numeric Column Types For Numeric Values (query line: 37): Referencing a numeric value (e.g. 35) as a string in a WHERE clause might result in poor performance. Possible impacts of storing numbers as varchars: more space will be used, you won't be able to perform arithmetic operations, the data won't be self-validated, aggregation functions like SUM won't work, the output may sort incorrectly and more. If the column is numeric, remove the quotes from the constant value, to make sure a numeric comparison is done.
Optimal indexes for this query:
ALTER TABLE `currencies` ADD INDEX `currencies_idx_id` (`id`);
ALTER TABLE `users` ADD INDEX `users_idx_active` (`active`);
The optimized query:
SELECT
users.id AS user_id,
users.cat AS cat,
from_currencies.id AS from_currency,
to_currencies.id AS to_currency,
change_from AS change_from,
change_to AS change_to,
users.site AS link,
users.username AS user_name,
users.email AS email,
users.active AS active,
from_currencies.name AS from_name,
from_currencies.sign AS from_sign,
to_currencies.name AS to_name,
to_currencies.sign AS to_sign
FROM
(SELECT
`deals_public`.change_from AS change_from,
`deals_public`.change_to AS change_to,
`deals_public`.`user_id` AS deals_public_user_id,
`deals_public`.`from_currency` AS deals_public_from_currency,
`deals_public`.`to_currency` AS deals_public_to_currency
FROM
`deals_public` LIMIT 20) AS `deals_public`
INNER JOIN
`users`
ON `users`.`id` = `deals_public`.deals_public_user_id
INNER JOIN
`currencies` AS `from_currencies`
ON `from_currencies`.`id` = `deals_public`.deals_public_from_currency
INNER JOIN
`currencies` AS `to_currencies`
ON `to_currencies`.`id` = `deals_public`.deals_public_to_currency
WHERE
`users`.`active` = 1
AND deals_public_from_currency = '34'
AND deals_public_to_currency = '35' LIMIT 20