MySQL查询执行时间过长。查询返回了良好的结果,但可能没有好的设计

时间:2015-03-09 10:21:21

标签: php mysql sql join count

这是我的问题的SQL小提琴:http://sqlfiddle.com/#!9/8ad87/2

我有桌子:群组优惠 offers_groups

组具有名称,但这些名称具有分配给它们的特殊ID。 Id不是自动递增的,它们是以这种方式预定义的。

以下是群组表格的一小部分:

id name 0300000 Agro 0310000 Fruits 0311000 Peach 0320000 Vegetables

商品表中存储了由人和公司提供的商品:

id offer 1 Selling fruits 2 Selling peanuts 3 Selling Vegetables 4 Selling peach 5 We do Agro 6 We sell Peach 7 We sell Vegetables 8 We transport Vegetables 9 We transport Peaches

offers_groups 表负责连接这两个:

id offer_id group_id 1 1 3100000 2 2 0300000 3 3 0311000 4 4 0300000 5 5 0311000 6 6 0320000 7 7 0320000 8 3 0311000

我需要计算哪些群组拥有最多优惠,并将这些群组展示给用户。

这是我的问题:

SELECT og.id, og.offer_id, og.group_id,
       o.id, o.offer,
       g.id, g.name,
       COUNT(og.offer_id) AS offersCount

FROM `offers_groups` og 

JOIN `offers` o ON og.offer_id = o.id
JOIN `groups` g ON og.group_id = g.id

GROUP BY og.group_id

ORDER BY offersCount DESC

LIMIT 2

我的SQL Fiddle中的代码正在工作,我认为它给了我正确的结果,但在真实的数据库中,这些表有很多数据,这个查询执行25秒。而且我不相信这是因为列索引,对吧?我希望有些专家可以告诉我我的查询是否设计得很糟糕。在获得正确结果的同时,我能做些什么来加快速度吗?

由于

1 个答案:

答案 0 :(得分:1)

首先,select中的所有列都没有意义。它们应该只处于“组”级别,而不是“提供组”级别。所以,让我关注这个问题:

SELECT g.id, g.name,
       COUNT(og.offer_id) AS offersCount
FROM `offers_groups` og JOIN
     `offers` o
     ON og.offer_id = o.id JOIN
     `groups` g
     ON og.group_id = g.id
GROUP BY g.id
ORDER BY offersCount DESC
LIMIT 2;

其次,在任何结构合理的数据库中,您实际上并不需要offers表 - 外键关系应该确保行实际存在。所以,试试这个:

SELECT g.id, g.name,
       COUNT(og.offer_id) AS offersCount
FROM `offers_groups` og JOIN
     `groups` g
     ON og.group_id = g.id
GROUP BY g.id
ORDER BY offersCount DESC
LIMIT 2;

然后,根据您的SQL Fiddle,您的表上没有索引。将所有id定义为主键。例如:

CREATE TABLE IF NOT EXISTS `offers` (
    `id` int(11) NOT NULL PRIMARY KEY,
    `offer` varchar(255) COLLATE utf8_unicode_ci NOT NULL
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=10 ;

使用主键可以解决您的性能问题。