[英]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.