2013-11-03 56 views
0

我正在運行的網站,我有兩個非常重複的查詢。而在MySQL中,innoDB進程可以看到他們花費了大量的時間,並且每當我看到那些在那裏的進程時,他們就一直在創建臨時表,並花費很長時間來執行大量內存和CPU。很多MySQL臨時表

他們真的很糟糕,我以某種方式設法優化這些......但我無法做到超越這一點。在模塊

 
- item_id 
- user_id 
- profile_id 
- uniq 

$getmoddetails = "SELECT a.id, a.name, a.defvar, a.description, a.icon, a.thumb, a.average_rating, a.total_rating, c.rating, a.group_access, d.long_name, a.editor_id, e.users_count 
     FROM dir_cat_item AS b 
     INNER JOIN dir_item AS a ON a.id = b.item_id 
     AND a.status = 'O' 
     LEFT JOIN dir_item_notation_user_map AS c ON a.id = c.item_id 
     AND c.user_id =%u 
     LEFT JOIN users AS d ON d.id = a.editor_id 
     LEFT JOIN (SELECT item_id, COUNT(*) AS users_count 
      FROM module 
      GROUP BY item_id) AS e ON e.item_id = b.item_id 
     WHERE a.id=%u"; 


$getnbModules_by_col = "SELECT 
          posx,COUNT(posx) as nb 
         FROM module WHERE 
          user_id = %u 
          AND profile_id = %u 
         GROUP BY posx 
         ORDER BY posx ASC"; 

表的索引,爲用戶表

 
- id 
- username 

任何建議,請...

更新: -

CREATE TABLE IF NOT EXISTS `module` (
    `item_id` mediumint(8) unsigned NOT NULL DEFAULT '0', 
    `user_id` int(10) unsigned NOT NULL DEFAULT '0', 
    `profile_id` int(3) unsigned NOT NULL DEFAULT '0', 
    `posx` tinyint(3) unsigned NOT NULL DEFAULT '0', 
    `posy` tinyint(3) unsigned NOT NULL DEFAULT '0', 
    `posj` tinyint(3) unsigned NOT NULL DEFAULT '0', 
    `x` smallint(5) unsigned NOT NULL DEFAULT '0', 
    `y` smallint(5) unsigned NOT NULL DEFAULT '0', 
    `typ` char(1) CHARACTER SET utf8 NOT NULL DEFAULT 'D', 
    `variables` text COLLATE utf8_unicode_ci, 
    `uniq` smallint(5) unsigned NOT NULL DEFAULT '1', 
    `blocked` tinyint(1) unsigned NOT NULL DEFAULT '0', 
    `minimized` tinyint(1) unsigned NOT NULL DEFAULT '0', 
    `old_id` tinyint(3) unsigned DEFAULT NULL, 
    `feed_id` mediumint(8) unsigned NOT NULL DEFAULT '0', 
    `shared` varchar(33) COLLATE utf8_unicode_ci DEFAULT NULL, 
    `currentview` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL, 
    KEY `item_id` (`item_id`,`user_id`,`profile_id`,`uniq`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; 

item_id 18 A No 
user_id 393467 A No 
profile_id 393467 A No 
uniq 393467 A No 

預先感謝您

+1

'EXPLAIN PLAN'和完整'SHOW CREATE語句TABLE'效果好嗎 – Sebas

回答

0

對於第二個查詢的最佳性能,你需要在module表,例如一個適當的索引

... ON module (item_id) 

但是,如果沒有列的表定義,數據類型和基數,這真是不可能的:

... ON module (user_id, profile_id, posx) 

對於第一個查詢,你很可能從不同的指數上module表格中受益。提出明確的建議。

在你的第一個查詢中,我建議你在內聯視圖(派生表)中添加一個謂詞,別名爲e。我不認爲MySQL會將外部查詢中的謂詞推入內聯視圖。

(SELECT item_id 
      , COUNT(*) AS users_count 
     FROM module 
     WHERE item_id = %u 
     GROUP BY item_id 
    ) AS e 

您將需要在WHERE子句中提供與您在外部查詢的WHERE子句中提供的值相同的值。從我正在讀那裏...

e.item_id = b.item_id = a.id = %u 

通過補充說,凡在該行內觀點條款,即應該減少數量或從模塊表中檢索行,並派生表將只有一行。具有前導列item_id的索引將是覆蓋索引。 EXPLAIN PLAN應顯示Using index而不顯示Using filesort


如果你的第一個查詢拉回相對較小的行數,你可以考慮在模塊表中的相關子查詢,代替你的第一個查詢中使用聯接到派生表(別名爲e) (以避免實現大的派生表)。 (但是,通常情況下,相關的子查詢可能是真正的性能殺手,但在某些情況下,如果外部查詢拉回少量的行,子查詢的重複執行實際上可能比生成大的派生表更好你只需要幾行。)

SELECT a.id 
    , a.name 
    , a.defvar 
    , a.description 
    , a.icon 
    , a.thumb 
    , a.average_rating 
    , a.total_rating 
    , c.rating 
    , a.group_access 
    , d.long_name 
    , a.editor_id 
    , (SELECT SUM(1) 
      FROM module e 
      WHERE e.item_id = b.item_id 
      AND e.item_id = %u 
     ) AS users_count 
    FROM dir_cat_item b 
    JOIN dir_item a 
    ON a.id = b.item_id 
    AND b.item_id = %u 
    AND a.status = 'O' 
    LEFT 
    JOIN dir_item_notation_user_map c 
    ON c.item_id = a.id 
    AND c.item_id = %u 
    AND c.user_id = %u 
    LEFT 
    JOIN users d 
    ON d.id = a.editor_id 
WHERE a.id = %u 
+0

嗨斯賓塞,感謝您迴應..我已經添加了第二個查詢和查詢cordinality結構.. – SmartDev

+0

對於第二個查詢,已經在user_id和profile_id上​​獲得了相等謂詞,因此這些索引範圍掃描必須是索引中的* leading *列;下一列需要是'posx';使用我建議的索引,MySQL可能能夠在沒有文件操作的情況下執行GROUP BY。這應該是一個覆蓋索引,所以'EXPLAIN PLAN'應該在額外列中顯示'使用索引',並且它不應該顯示'使用filesort'。 – spencer7593

+0

更新後的答案增加了在第二個查詢WHERE item_id =%u'中將謂詞添加到內聯視圖的建議。 – spencer7593