【问题标题】:GROUP BY OptimizationGROUP BY 优化
【发布时间】:2009-08-28 10:01:50
【问题描述】:

嘿。我有这两个表的 1:n 关系。

CREATE TABLE IF NOT EXISTS `de_locations` (
`id` int(11) NOT NULL auto_increment,
`user_id` int(11) default NULL,
`author_id` int(11) NOT NULL,
`city_id` int(11) NOT NULL,
`district_id` int(11) NOT NULL,
`title` varchar(150) collate utf8_unicode_ci NOT NULL,
`description` tinytext collate utf8_unicode_ci,
`lat` double NOT NULL,
`lng` double NOT NULL,
`stars` double default '0',
`comments` mediumint(9) default '0',
`flag` tinyint(4) default '0',
PRIMARY KEY  (`id`),
KEY `user_id` (`user_id`),
KEY `flag` (`flag`),
KEY `rating_district` (`district_id`,`stars`,`comments`),
KEY `rating_city` (`city_id`,`stars`,`comments`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=15 ;

CREATE TABLE IF NOT EXISTS `de_location2category` (
`id` int(11) NOT NULL auto_increment,
`location_id` int(11) NOT NULL,
`cat_id` mediumint(9) NOT NULL,
PRIMARY KEY  (`id`),
UNIQUE KEY `rel` (`location_id`,`cat_id`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=14 ;

一个位置可以放在多个类别中。

例如:

地点:“必胜客” 类别:“意大利食品”、“快餐”

这些类别是父类别食物的子类别。

现在我想选择食物类别中的所有位置。

SELECT a.id, a.title, a.description, a.street, a.hnr, ROUND(a.stars) as stars, a.comments, a.lat, a.lng
FROM de_locations as a 
INNER JOIN de_location2category as b
ON b.location_id = a.id
WHERE b.cat_id BETWEEN 0 AND 100 
AND a.city_id = 1000 
GROUP BY a.id
ORDER BY a.stars DESC, a.comments DESC

我需要 GROUP BY,因为如果位置与多个类别相关,我不想要重复的位置。但是这个查询会构建一个临时表并使用文件排序。如果我离开 GROUP BY 一切都很好,但我需要它……

我必须添加另一个索引吗?还是我的方案有什么问题? 你将如何解决这个问题?非常感谢。

【问题讨论】:

  • "但是这个查询构建了一个临时表并使用了文件排序。"所以呢?这就是关系数据库的工作方式。那有什么问题?您还建议如何删除重复项?
  • dev.mysql.com/doc/refman/5.0/en/order-by-optimization.html "在某些情况下,MySQL 无法使用索引来解析 ORDER BY,尽管它仍然使用索引来查找与 WHERE 子句匹配的行。这些情况包括:您在不同的键上使用 ORDER BY:SELECT * FROM t1 ORDER BY key1, key2;"
  • “这有什么问题?”表现。在简单的 SELECT 中,GROUP BY 并不总是强制临时表。在这种情况下没有办法实现这一点吗? GROUP BY 也不使用索引“rating_city”。
  • 嘿,戴夫。是的,我已阅读“按优化排序”文档。但我无法找到解决方案。这根本不可能吗?或者我可以通过更改索引或 SELECT 来获得更好的性能吗?到目前为止感谢
  • 黑白分明:如果您使用多个键进行排序,那么您将使用文件排序。

标签: mysql optimization group-by


【解决方案1】:

我认为您的问题是查询速度很慢。无需担心临时和文件排序,但是为什么查询很慢。 添加 EXPLAIN {yourquery} 的输出,以便我们检查到底发生了什么。

或者你也可以试试子查询:

SELECT a.id, a.title, a.description, a.street, a.hnr, ROUND(a.stars) as stars, a.comments, a.lat, a.lng
FROM de_locations as a 
WHERE 
a.id IN (SELECT DISTINCT b.location_id FROM de_location2category as b WHERE b.cat_id BETWEEN 0 AND 100)
AND a.city_id = 1000 
GROUP BY a.id
ORDER BY a.stars DESC, a.comments DESC

【讨论】:

    【解决方案2】:

    为什么不直接使用DISTINCTa.id ?

    【讨论】:

    • 与 GROUP BY 的结果相同:临时表和文件排序
    • 是的,这几乎是给定的,因为您正在按多个键进行排序。只是 DISTINCT 比 GROUP BY 更好地描述了您实际尝试实现的目标。
    • 我是否理解正确,问题是我在 WHERE 子句中使用了索引“rel”,在 ORDER BY 子句中使用了索引“rating_city”?正因为如此,我没有机会只更改索引?所以我必须忍受临时表和文件排序?抱歉,遇到了一些语言问题...
    猜你喜欢
    • 1970-01-01
    • 2012-12-31
    • 2011-08-29
    • 1970-01-01
    • 2021-10-11
    • 2014-05-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多