2011-12-22 84 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