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 LIKE Searches With Leading Wildcard (query line: 14): The database will not use an index when using like searches with a leading wildcard (e.g. '%grge%'). Although it's not always a satisfactory solution, please consider using prefix-match LIKE patterns (e.g. 'TERM%').
- Avoid LIKE Searches With Leading Wildcard (query line: 26): The database will not use an index when using like searches with a leading wildcard (e.g. '%adf%'). Although it's not always a satisfactory solution, please consider using prefix-match LIKE patterns (e.g. 'TERM%').
- Avoid OFFSET In LIMIT Clause (query line: 29): OFFSET clauses can be very slow when used with high offsets (e.g. with high page numbers when implementing paging). Instead, use the following \u003ca target\u003d"_blank" href\u003d"http://www.eversql.com/faster-pagination-in-mysql-why-order-by-with-limit-and-offset-is-slow/"\u003eseek method\u003c/a\u003e, which provides better and more stable response rates.
- Avoid OFFSET In LIMIT Clause (query line: 16): OFFSET clauses can be very slow when used with high offsets (e.g. with high page numbers when implementing paging). Instead, use the following \u003ca target\u003d"_blank" href\u003d"http://www.eversql.com/faster-pagination-in-mysql-why-order-by-with-limit-and-offset-is-slow/"\u003eseek method\u003c/a\u003e, which provides better and more stable response rates.
- Avoid OFFSET In LIMIT Clause (query line: 28): OFFSET clauses can be very slow when used with high offsets (e.g. with high page numbers when implementing paging). Instead, use the following \u003ca target\u003d"_blank" href\u003d"http://www.eversql.com/faster-pagination-in-mysql-why-order-by-with-limit-and-offset-is-slow/"\u003eseek method\u003c/a\u003e, which provides better and more stable response rates.
- 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 UNION ALL instead of UNION (query line: 18): 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:
ALTER TABLE `Company` ADD INDEX `company_idx_userid` (`userId`);
ALTER TABLE `Personal` ADD INDEX `personal_idx_userid` (`userId`);
ALTER TABLE `User` ADD INDEX `user_idx_id` (`id`);
ALTER TABLE `User` ADD INDEX `user_idx_type_id` (`type`,`id`);
The optimized query:
SELECT
userId,
userType
FROM
((SELECT
DISTINCT u.id AS userId,
u.type AS userType
FROM
User AS u,
Personal AS p,
Company AS c
WHERE
(
c.name LIKE '%grge%'
AND u.id = c.userId
) LIMIT 0, 10000)
UNION
DISTINCT (SELECT
DISTINCT u.id AS userId,
u.type AS userType
FROM
User AS u,
Personal AS p,
Company AS c
WHERE
(p.realName LIKE '%adf%'
AND u.type = 1
AND u.id = p.userId) LIMIT 0, 10000)
) AS union1 LIMIT 0, 10000