如何提高此查询的效果,同时获取所需的所有信息..
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
目前,此查询在7-10秒内运行。
ticket_request
表有大约100k行customers
表有大约300k行users
表格和ticket_type
没有那么多(约1k行)答案 0 :(得分:1)
下面的加速技术是首先取消LIMIT
,只有在此之后,才能完成所有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
“衍生”表tr2中的JOINs
之后仅触及20行;这是加速的主要原因。
这可能同样好:
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
答案 1 :(得分:0)
我假设您使用的是MySQL。如果没有,可以稍微修改这个答案以适应另一个数据库,但概念应该保持不变。您可以使用ticket_request
列向左连接右侧所涉及的所有ID列添加索引:
ALTER TABLE ticket_type ADD INDEX (id);
ALTER TABLE users ADD INDEX (id);
ALTER TABLE customer ADD INDEX (id); -- important
要解释索引有用的原因,请考虑LEFT JOIN
表和ticket_request
表之间的第一个ticket_type
。如果没有索引,对于ticket_request
中的每个记录,数据库必须扫描整个ticket_type
表以查找与连接条件匹配的记录。从性能的角度来看,这是昂贵的。但是使用索引,数据库可以更快地完成此操作,因为它“知道”匹配记录的确切位置(或几乎完全准确)。
虽然您提到只有customer
表非常大,但您仍然可以将索引添加到其他表中。将来,它们也可能变大。最有可能涉及customer
的联接是您查询的瓶颈。
答案 2 :(得分:0)
此处优化的最大机会是使用LIMIT 0,20
GROUP BY tr.id
毫无意义,应该删除。
create index ticket_request_ix_is_deleted_created_date on ticket_request (is_deleted,created_date)
并将tr.is_deleted != 1
更改为tr.is_deleted = 0
。
或者
create index ticket_request_ix_created_date on ticket_request (created_date)
答案 3 :(得分:0)
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
尝试此操作可以提高性能并根据您的要求进行调整
答案 4 :(得分:-1)
除了索引之外,在应用程序级别,您可以使用 Memcached (如果您使用的是php)这样的东西。这也将为您带来出色的表现。