How do I improve performance this query while also get all the information needed..
SELECT
tr.id, tr.request_status, tr.note, tr.created_date,
c.name AS customer_name, c.mobile_phONe,
u.full_name AS created_by_name, tt.name AS ticket_type_name
FROM
ticket_request tr
LEFT JOIN
ticket_type tt ON tt.id = tr.ticket_type_id
LEFT JOIN
users u ON u.id = tr.created_by
LEFT JOIN
customer c ON c.id = tr.customer_id
WHERE
tr.is_deleted != 1
AND tr.user_id IN (SELECT u.id FROM users u WHERE u.status = '1')
GROUP BY
tr.id
ORDER BY
tr.created_date DESC
LIMIT 0,20
Currently, this query runs in 7-10 seconds.
ticket_request
table has about 100k rows customers
table has about 300k rows users
table and ticket_type
don't have that much (about 1k rows) The speedup technique below is to dispense with the LIMIT
first , and only after that, do all the JOINs
.
SELECT tr3.id, tr3.request_status, tr3.note, tr3.created_date,
c.name AS customer_name, c.mobile_phONe,
u2.full_name AS created_by_name,
tt.name AS ticket_type_name
FROM
(
SELECT tr1.id
FROM ticket_request tr1
JOIN users u1 ON u1.id = tr1.created_by
WHERE u1.status = '1'
AND tr1.is_deleted != 1
ORDER BY tr1.created_date DESC
LIMIT 0,20
) AS tr2
JOIN ticket_request AS tr3 ON tr3.id = tr2.id
JOIN user AS u2 ON u2.id = tr3.created_by
LEFT JOIN ticket_type tt ON tt.id = tr3.ticket_type_id
LEFT JOIN customer c ON c.id = tr3.customer_id
ORDER BY tr3.created_date
The JOINs
, after the one in the "derived" table tr2, are touching only 20 rows; this is much of the speedup.
This may be equally good:
SELECT d.id, d.request_status, d.note, d.created_date,
c.name AS customer_name, c.mobile_phONe, d.created_by_name,
tt.name AS ticket_type_name
FROM
(
SELECT tr.id AS tr_id, tr.request_status, tr.note, tr.created_date,
tr.ticket_type_id, tr.customer_id
u.full_name AS created_by_name
FROM ticket_request tr
JOIN users u ON u.id = tr.created_by
WHERE u.status = '1'
AND tr.is_deleted != 1
ORDER BY tr.created_date DESC
LIMIT 0,20
) AS d
LEFT JOIN ticket_type tt ON tt.id = d.ticket_type_id
LEFT JOIN customer c ON c.id = d.customer_id
ORDER BY d.created_date
I'm assuming that you are using MySQL. If not, this answer can be slightly modified to fit another database, but the concept should remain the same. You can add indices to all the ID columns which are involved in the right hand side of your left joins with the ticket_request
column:
ALTER TABLE ticket_type ADD INDEX (id);
ALTER TABLE users ADD INDEX (id);
ALTER TABLE customer ADD INDEX (id); -- important
To explain why an index would help, consider the first LEFT JOIN
between your ticket_request
table and the ticket_type
table. Without an index, for each record in ticket_request
the database would have to potentially scan the entire ticket_type
table to find records which match the join condition. This is costly from a performance point of view. But with an index, the database can complete this operation much faster, since it "knows" where to look exactly (or almost exactly) for the matching records.
Though you mentioned that only the customer
table is very large, you can still add indices to the other tables. In the future, they might get larger too. Most likely the join involving customer
is the bottleneck in your query.
The biggest opportunity for optimization here is with LIMIT 0,20
GROUP BY tr.id
make no sense and should be removed.
create index ticket_request_ix_is_deleted_created_date on ticket_request (is_deleted,created_date)
and change tr.is_deleted != 1
to tr.is_deleted = 0
.
Or
create index ticket_request_ix_created_date on ticket_request (created_date)
SELECT
tr.id, tr.request_status, tr.note, tr.created_date,
c.name AS customer_name, c.mobile_phONe,
u.full_name AS created_by_name, tt.name AS ticket_type_name
FROM
ticket_request tr
LEFT JOIN
ticket_type tt ON tt.id = tr.ticket_type_id and tr.is_deleted != 1
LEFT JOIN
users u ON u.id = tr.created_by
JOIN
users u1 ON u1.id = tr.user_id and u1.status = '1'
LEFT JOIN
customer c ON c.id = tr.customer_id
GROUP BY
tr.id
ORDER BY
tr.created_date DESC
LIMIT 0,20
try this it will work with improved performance and tweak as per your requirement
Other than indexing , On application level you can use Memcached ( in case you are using php) like stuffs. This will also give you great performance.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.