我有这个查询需要至少1分钟才能运行。它使用了很多左连接。 有没有办法让它更快?我是SQL的新手,所以请帮助。
SELECT
distinct cnt.last_name,
cnt.bus_ph_num,
cnt.email_addr,
usr.login,
cnt.fst_name,
cnt.fk_id
from
contact cnt
LEFT JOIN
transaction tran
ON tran.id=cnt.fk_id
left join
party party
on party.pk_id=cnt.fk_id
left join
user usr
on usr.fk_id=cnt.fk_id
left join
role role
on
usr.role_id = role.pk_row_id
where
cnt.status_cd=1
and party.fk_id= 'xyz'
and (
usr.login like '%somevalue%'
and (
tran.txn_trk_num is null || tran.txn_trk_num like '%somevalue%'
)
and cnt.last_name like '%somevalue%'
and cnt.email_addr like '%somevalue%'
and cnt.busin_ph_num like '%somevalue%'
)
and (
tran.txn_trk_num is null || tran.txn_typ=1 || tran.txn_typ=2 || tran.txn_typ=3
)
and (role.role_name ='ROLE_ADMIN')
答案 0 :(得分:2)
对,我试图尽我所能。主要是一些重新排序,一些交换到INNER JOIN并将WHERE语法移动到连接。一些别名的重命名,因为您使用了与表名匹配的别名,否定了它们的用途。
这将返回没有匹配事务的行,因此您可能希望将该连接更改为INNER,而不是取决于目的/预期输出,但这应该是一个很好的起点。它允许MySQL减少它看到的行数。
可以通过合适的索引进一步改进,但是如果不了解数据类型/数据的差异等,就可以提出建议。
SELECT DISTINCT
cnt.last_name,
cnt.bus_ph_num,
cnt.email_addr,
u.login,
cnt.fst_name,
cnt.fk_id
FROM contact cnt
-- Changed to INNER JOIN as the WHERE indicates this is required
INNER JOIN party p
ON p.pk_id=cnt.fk_id
-- Moved this limiting statement to the join
AND p.fk_id= 'xyz'
-- Changed to INNER JOIN as the LIKE % indicates htis is required
INNER JOIN user u
ON u.fk_id=cnt.fk_id
-- OP added later, quite inefficient due to use of wildcards on both sides causing scans
AND u.login LIKE '%somevalue%'
-- Also here, INNER, as the WHERE means this is required
INNER JOIN role r
ON r.pk_row_id = u.role_id
-- Moved this limiting statement to the join
AND r.role_name ='ROLE_ADMIN'
LEFT JOIN transaction tran
ON tran.id=cnt.fk_id
-- Moved this limiting statement to the join
AND tran.txn_typ IN ( 1 , 2 , 3 )
-- OP added later, quite inefficient due to use of wildcards on both sides causing scans
AND tran.txn_trk_num LIKE '%somevalue%'
WHERE cnt.status_cd = 1
-- OP added later, quite inefficient due to use of wildcards on both sides causing scans
AND cnt.last_name LIKE '%somevalue%'
AND cnt.email_addr LIKE '%somevalue%'
AND cnt.busin_ph_num LIKE '%somevalue%'
如果你能摆脱那些LIKE语句,它也会变得更好。如果有合适的索引,以下内容可以使用索引:
... LIKE 'somevalue'
... = 'somevalue'
... LIKE 'somevalue%'
但是... LIKE '%somevalue%'
无法使用索引