我正在运行的网站,我有两个非常重复的查询。在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
对于USERS表
- 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
提前谢谢
答案 0 :(得分:0)
为了获得第二个查询的最佳性能,您需要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