簡體   English   中英

MySQL中有很多臨時表

[英]Lots of temporary tables in MySQL

我正在運行的網站下面有兩個非常重復的查詢。 在MySQL中,innoDB進程可以看到它們花費大量時間,並且每當我看到那里的進程時,它們就會繼續創建臨時表,並且要花很長時間執行並占用大量內存和CPU。

他們真的很糟糕,我以某種方式設法優化了這些。但是我無法做到這一點。

$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";

模塊上的表索引

- item_id
- user_id
- profile_id
- uniq

對於用戶表

- 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

先感謝您

為了使第二個查詢獲得最佳性能,您需要在module表上有適當的索引,例如

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

對於第一個查詢,您可能會受益於module表上的其他索引:

... ON module (item_id)

但是,如果沒有表定義,列的數據類型和基數,就不可能提出明確的建議。

在您的第一個查詢中,建議您在內聯視圖(派生表)中添加別名為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

通過在該內聯視圖中添加該WHERE子句,應該可以減少從模塊表中檢索到的行數,並且該派生表將只有一行。 前導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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM