2
我很久以来一直在为这个问题而苦苦挣扎。该查询运行在一个较小的数据相当快的设置,但是当表增长至100K +行从30年代花费几分钟的时间来运行:使用“不为空”的左连接查询的优化
SELECT accounts.id
, accounts.name
, ..etc..
FROM accounts
LEFT JOIN (
SELECT distinct secr.record_id as id
FROM securitygroups secg
INNER JOIN securitygroups_users secu
ON secg.id = secu.securitygroup_id
AND secu.deleted = 0
AND secu.user_id = 'seed_chris_id'
INNER JOIN securitygroups_records secr
ON secg.id = secr.securitygroup_id
AND secr.deleted = 0
AND secr.module = 'Accounts'
WHERE secg.deleted = 0
) securitygroup_join ON securitygroup_join.id = accounts.id
WHERE ((accounts.assigned_user_id ='seed_chris_id'
OR securitygroup_join.id is not null))
AND accounts.deleted=0
ORDER BY
accounts.date_entered
DESC LIMIT 0,21
基本上它应该返回该用户拥有记录(占所有行。 assigned_user_id)或者是与记录关联的组的成员(securitygroup_join.id不为空)。该查询由框架以特定的方式构建,因此面临一些限制。一个不可能轻易实现的解决方案是将其更改为UNION。想要避开那条路线。在过去做了“where ... in”条款,但表现更糟。我可以根据需要添加到join,where子句或操作索引,但对查询结构的任何其他重大更改都无法轻松完成。
+1:肯定值得一试。 MS SQL Server对此做了很好的优化,MySQL也可以这样做,试试:) – MatBailie 2011-12-23 00:02:37
针对securitygroups_records表中700k行的数据库,建议更改的数据大约在3.2s内执行,而原始查询在17.8s内执行。我会说这是一个很好的改进:)。不开心,我没有想到首先存在。谢谢! – egg 2011-12-23 03:34:56
太棒了!很高兴我能帮上忙。 – 2011-12-23 14:08:31