2011-12-22 86 views
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子句或操作索引,但对查询结构的任何其他重大更改都无法轻松完成。

回答

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 

我没有测试过这一点,所以它可能不会有更好的表现,但它是值得一试。

+0

+1:肯定值得一试。 MS SQL Server对此做了很好的优化,MySQL也可以这样做,试试:) – MatBailie 2011-12-23 00:02:37

+0

针对securitygroups_records表中700k行的数据库,建议更改的数据大约在3.2s内执行,而原始查询在17.8s内执行。我会说这是一个很好的改进:)。不开心,我没有想到首先存在。谢谢! – egg 2011-12-23 03:34:56

+0

太棒了!很高兴我能帮上忙。 – 2011-12-23 14:08:31