我有一个像
这样的mysql查询 SELECT `tbl_ticket`.`id`, `tbl_ticket`.`hd_user_username`,
`tbl_ticket`.`hd_user_email`, `tbl_ticket`.`ticket_title`,
`tbl_complain_type`.`complains` FROM `tbl_ticket` LEFT JOIN
`tbl_ticket_complain` ON tbl_ticket_complain.ticket_id=tbl_ticket.id
LEFT JOIN `tbl_complain_type` ON tbl_complain_type.id=tbl_ticket_complain.complain_id
LEFT JOIN `tbl_assignment` ON tbl_assignment.ticket_id=tbl_ticket.id
WHERE ((((`hd_user_username` LIKE '%searchterm%')
AND (`tbl_assignment`.`id` IN ($array)))
OR (`hd_user_email`='searchterm'))
OR (`ticket_title`='searchterm')) OR (`tbl_complain_type`.`complains`='searchterm')
$array contains around 7000 values like `$array=array(1,2,3,..)`
此查询大约需要8秒钟才能执行。这个查询有替代解决方案吗? $ array的值来自另一个查询
select max(id) from tbl_assignment group by ticket_id
查询的缓慢是由于表之间的多个连接
答案 0 :(得分:3)
如果数组中的值使用IN IN子句来自一个选择,你可以使用这个事实 IN子句相当于内部连接,因此您可以使用your_table_with_id和table.column之间的内部联接来匹配,例如:
SELECT `
tbl_ticket`.`id`
, `tbl_ticket`.`hd_user_username`
, `tbl_ticket`.`hd_user_email`
, `tbl_ticket`.`ticket_title`
, `tbl_complain_type`.`complains`
FROM `tbl_ticket`
LEFT JOIN `tbl_ticket_complain` ON tbl_ticket_complain.ticket_id=tbl_ticket.id
LEFT JOIN `tbl_complain_type` ON tbl_complain_type.id=tbl_ticket_complain.complain_id
LEFT JOIN `tbl_assignment` ON tbl_assignment.ticket_id=tbl_ticket.id
INNER JOIN your_table_with_id ON `tbl_assignment`.`id` = JOIN your_table_with_id.id
WHERE ((((`hd_user_username` LIKE '%searchterm%')
OR (`hd_user_email`='searchterm'))
OR (`ticket_title`='searchterm')) OR (`tbl_complain_type`.`complains`='searchterm')
还要记住,使用IN子句的值的内容是有限的,并且在超出限制时失败
,在你的情况下
SELECT `
tbl_ticket`.`id`
, `tbl_ticket`.`hd_user_username`
, `tbl_ticket`.`hd_user_email`
, `tbl_ticket`.`ticket_title`
, `tbl_complain_type`.`complains`
FROM `tbl_ticket`
LEFT JOIN `tbl_ticket_complain` ON tbl_ticket_complain.ticket_id=tbl_ticket.id
LEFT JOIN `tbl_complain_type` ON tbl_complain_type.id=tbl_ticket_complain.complain_id
LEFT JOIN `tbl_assignment` ON tbl_assignment.ticket_id=tbl_ticket.id
INNER JOIN (
select max(id) as id
from tbl_assignment
group by ticket_id
) t ON `tbl_assignment`.`id` = t.id
WHERE ((((`hd_user_username` LIKE '%searchterm%')
OR (`hd_user_email`='searchterm'))
OR (`ticket_title`='searchterm')) OR (`tbl_complain_type`.`complains`='searchterm'))
答案 1 :(得分:0)
这基本上是您的查询:
SELECT . . .
FROM tbl_ticket t LEFT JOIN
tbl_ticket_complain tc
ON tc.ticket_id = t.id LEFT JOIN
tbl_complain_type tct
ON tct.id = tc.complain_id LEFT JOIN
tbl_assignment a
ON a.ticket_id = t.id
WHERE (((hd_user_username LIKE '%searchterm%' AND
a.id IN ($array)
) OR
`hd_user_email`='searchterm'
) OR
ticket_title = 'searchterm'
) OR
tct.complain` = 'searchterm';
性能问题与IN
无关。实际上,MySQL会优化IN
,如documentation:
如果所有值都是常量,则根据类型评估它们 expr和排序。然后使用a完成对项目的搜索 二分搜索。这意味着,如果
IN
值列表,IN
非常快 完全由常数组成。
你不会比带有常数的IN
列表更快。
您的查询问题是OR
s的字符串。优化器几乎不可能使用索引 - 因此必须创建完整的结果集然后过滤掉。
我很难看到如何在查询中改进这一点。有时,将查询拆分为更简单的块并使用union
或union all
连接它们就可以了。您的条件有点难以理解,这使得这种方法对于局外人来说很难。