我很长时间都在努力解决这个问题。此查询在较小的数据集上运行相当快,但当表增长到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
基本上它应该返回用户拥有记录的所有行(accounts.assigned_user_id)或者是与记录关联的组的成员(securitygroup_join.id不为null)。此查询由框架以特定方式构建,因此面临一些约束。一个不容易实现的可能解决方案是将其更改为UNION。想避开那条路线。在过去做了“where ... in”条款,但表现更差。我可以根据需要添加到join,where子句或操作索引,但是查询结构的任何其他重大更改都不容易完成。
答案 0 :(得分:3)
您可以尝试使用WHERE EXISTS
代替LEFT JOIN
。例如:
SELECT accounts.id
, accounts.name
, ..etc..
FROM accounts
WHERE (( accounts.assigned_user_id ='seed_chris_id'
OR EXISTS (SELECT 1
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 secr.record_id = accounts.id
AND secg.deleted = 0)
))
AND accounts.deleted=0
ORDER BY
accounts.date_entered
DESC LIMIT 0,21
我没有对此进行测试,因此可能效果不佳,但值得尝试。