2013-03-21 156 views
0

QUERY:MySQL的:很慢使用嵌套子查詢的查詢

SELECT 
    (
     SELECT COUNT(cleanpoi.ID) FROM cleanpoi 
     WHERE cleanpoi.EstablishmentID=parent.ID 
    ) AS POIs, 
    (
     SELECT COUNT(ID) FROM cleanamenitymappings WHERE CleanPOIID IN 
     (
      SELECT cleanpoi.ID FROM cleanpoi 
      WHERE cleanpoi.EstablishmentID=parent.ID 
     ) 
    ) AS Amenities, 
    (
     SELECT COUNT(ID) FROM cleanamenityvalues WHERE CleanPOIID IN 
     (
      SELECT cleanpoi.ID FROM cleanpoi 
      WHERE cleanpoi.EstablishmentID=parent.ID 
     ) 
    ) AS AmenityValues 
    FROM establishment parent 
    WHERE parent.ID=3 

EXPLAIN結果:

id select_type   table     type    possible_keys        key    key_len ref  rows Extra      
------ ------------------ -------------------- --------------- ----------------------------------------- --------------- ------- ------ ------ -------------------------- 
    1 PRIMARY    parent    const   PRIMARY         PRIMARY   4  const  1 Using index    
    5 DEPENDENT SUBQUERY cleanamenityvalues ALL    (NULL)          (NULL)   (NULL) (NULL) 31778 Using where    
    6 DEPENDENT SUBQUERY cleanpoi    unique_subquery PRIMARY,EstablishmentID_2,EstablishmentID PRIMARY   4  func   1 Using where    
    3 DEPENDENT SUBQUERY cleanamenitymappings index   (NULL)          CleanPOIID  4  (NULL) 673591 Using where; Using index 
    4 DEPENDENT SUBQUERY cleanpoi    unique_subquery PRIMARY,EstablishmentID_2,EstablishmentID PRIMARY   4  func   1 Using where    
    2 DEPENDENT SUBQUERY cleanpoi    ref    EstablishmentID_2,EstablishmentID   EstablishmentID 4  const  181  

與此查詢有何建議?你的答案真的很感謝!

+1

爲了提高性能,刪除嵌套查詢或增加你的'innodb_buffer_pool_size' – 2013-03-21 06:44:01

+1

爲什麼你發佈一個答案,一個評論? – 2013-03-21 06:45:55

回答

0

感謝所有的答案,但這解決了我的問題。

SELECT 
    (
     SELECT COUNT(cleanpoi.ID) FROM cleanpoi 
     WHERE cleanpoi.EstablishmentID=parent.ID 
    ) AS POIs, 
    (
     SELECT COUNT(a.ID) 
     FROM cleanamenitymappings a LEFT JOIN cleanpoi b ON a.CleanPOIID=b.ID 
     WHERE b.EstablishmentID=parent.ID 
    ) AS Amenities, 
    (
     SELECT COUNT(a.ID) 
     FROM cleanamenityvalues a LEFT JOIN cleanpoi b ON a.CleanPOIID=b.ID 
     WHERE b.EstablishmentID=parent.ID 
    ) AS AmenityValues 
    FROM establishment parent 
    WHERE parent.ID=3 
0

您的查詢確實掃描了700k行,所有需要從磁盤讀取的行。我猜測磁盤性能差(帶寬和/或尋道時間)。

如果經常運行此查詢,考慮創建一個物化視圖,這是拿着答案的整個查詢和更新使用觸發器時,數據的變化的表。

0

我會用中間結果創建臨時表,然後從這個臨時表中選擇。

這可能是有用的,以創建一個存儲過程做到這一點:

delimiter ;; 
create procedure MyLongProcedure() 
begin 
    -- Just in case, drop the temporary tables before creating them 
    drop table if exists temp_step01; 
    -- Make a temporary table for each subquery 
    create temporary table temp_step01 
     select ... ; 
    -- Be sure to create the appropriate indexes for each temporary table 
    alter table temp_step01 
     add index .... ; 
    -- Create as much tables as you need 
    -- Finally, execute your final query using all the tables you just created 
    select ... ; 
end;; 
delimiter ; 

記住:臨時表可以由創建它們的連接讀取。在多用戶環境中,根據您的具體需求,可以使用或不使用。

這只是一個想法。希望它可以幫助你。

+0

這可能會有幫助。我會盡快嘗試。我仍在尋找更好的解決方案。 – 2013-03-21 07:19:48