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 Calling Functions With Indexed Columns (query line: 19): When a function is used directly on an indexed column, the database's optimizer won’t be able to use the index. For example, if the column `last_name` is indexed, the index won’t be used as it’s wrapped with the function `lower`. If you can’t find an alternative condition that won’t use a function call, a possible solution is to store the required value in a new indexed column.
- Avoid Calling Functions With Indexed Columns (query line: 19): When a function is used directly on an indexed column, the database's optimizer won’t be able to use the index. For example, if the column `first_name` is indexed, the index won’t be used as it’s wrapped with the function `lower`. If you can’t find an alternative condition that won’t use a function call, a possible solution is to store the required value in a new indexed column.
- Avoid Calling Functions With Indexed Columns (query line: 31): When a function is used directly on an indexed column, the database's optimizer won’t be able to use the index. For example, if the column `code` is indexed, the index won’t be used as it’s wrapped with the function `lower`. If you can’t find an alternative condition that won’t use a function call, a possible solution is to store the required value in a new indexed column.
- Avoid OR Conditions By Using UNION (modified query below): In mosts cases, filtering using the OR operator cannot be applied using indexes. A more optimized alternative will be to split the query to two parts combined with a UNION clause, while each query holds one part of the original OR condition.
- 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.
- 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 `lushijo`.
- Use UNION ALL instead of UNION (query line: 22): Always use UNION ALL unless you need to eliminate duplicate records. By using UNION ALL, you'll avoid the expensive distinct operation the database applies when using a UNION clause.
Optimal indexes for this query:
CREATE INDEX players_idx_team_id ON "players" ("team_id");
The optimized query:
SELECT
players_id,
players_first_name,
players_last_name,
players_code
FROM
((SELECT
"players"."id" AS players_id,
"players"."first_name" AS players_first_name,
"players"."last_name" AS players_last_name,
"players"."code" AS players_code
FROM
"players"
WHERE
(
"players".team_id = 3
)
AND (
lower(replace("players".last_name || "players".first_name, ' ', '')) LIKE '%lushijo%'
) LIMIT 15)
UNION
DISTINCT (SELECT
"players"."id" AS players_id,
"players"."first_name" AS players_first_name,
"players"."last_name" AS players_last_name,
"players"."code" AS players_code
FROM
"players"
WHERE
("players".team_id = 3)
AND (lower("players".code) = 'lushijo') LIMIT 15)
) AS union1 LIMIT 15