已解决见下文
我在我的查询中尝试使用GROUP BY
和ORDER BY
,我检索按难度排序的数据。我必须使用GROUP BY
,因为GROUP CONCAT
因为某些表(例如'lookup_peripheral')将多个值链接到同一个键(content_id)。我理解为什么MYSQL在执行此任务时不能使用索引,因为GROUP BY和ORDER BY语句不共享相同的字段。但是,我正在寻找替代解决方案,不需要一天的时间来检索结果。
如果省略GROUP BY
或ORDER BY
子句,则数据库使用索引,但结果缺少所有外围设备或者没有按难度排序。
我在FROM
中使用'lookup_difficulty'表,所以我可以使用该索引来排序结果。 lookup_xxxxx
表存储每个允许的值,然后其他表(例如peripheral
)通过content_id将提交链接到值。所有内容都以提交content_id
为参考。 content
表包含成员ID,名称等基本信息。
如果我的帖子不够明确,我道歉。
mysql> describe peripheral;
+------------------+----------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+------------------+----------+------+-----+---------+-------+
| peripheral_id | int(2) | NO | PRI | NULL | |
| peripheral | char(30) | NO | | NULL | |
| peripheral_total | int(5) | NO | | NULL | |
+------------------+----------+------+-----+---------+-------+
mysql> select * from peripheral;
+---------------+-----------------+------------------+
| peripheral_id | peripheral | peripheral_total |
+---------------+-----------------+------------------+
| 1 | periph 1 | 0 |
| 2 | periph 2 | 1 |
| 3 | periph 3 | 3 |
+---------------+-----------------+------------------+
mysql> describe lookup_peripheral;
+---------------+---------+------+------+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+---------------+---------+------+------+---------+-------+
| content_id | int(10) | NO | INDEX| NULL | |
| peripheral_id | int(2) | NO | | NULL | |
+---------------+---------+------+------+---------+-------+
mysql> mysql> select * from lookup_peripheral;
+------------+---------------+
| content_id | peripheral_id |
+------------+---------------+
| 74 | 2 |
| 74 | 5 |
| 75 | 2 |
| 75 | 5 |
| 76 | 3 |
| 76 | 4 |
+------------+---------------+
以下不是在lookup_difficulty上使用索引,而是使用表排序和临时表。
SELECT group_concat(DISTINCT peripheral.peripheral) as peripheral, content.member, .....
FROM (lookup_difficulty)
LEFT OUTER JOIN lookup_peripheral ON lookup_difficulty.content_id = lookup_peripheral.content_id
LEFT OUTER JOIN peripheral ON peripheral.peripheral_id = lookup_peripheral.peripheral_id
.....
LEFT OUTER JOIN programmer ON programmer.programmer_id = lookup_programmer.programmer_id
LEFT OUTER JOIN lookup_programming_language ON lookup_difficulty.content_id = lookup_programming_language.content_id
GROUP BY lookup_difficulty.content_id
ORDER BY lookup_dfficulty.difficulty_id
LIMIT 30
最终目标是通过附加的正确外围设备检索按难度排序的结果。我想我需要一个子查询来实现这个目标。
编辑:下面回答:
想出来。我做了我怀疑我必须做的事情,那就是添加一个子查询。由于MYSQL每个表只能使用一个索引,因此我无法将GROUP BY
和SORT BY
一起用于我的特定设置。相反,我添加了另一个查询,该查询将使用另一个表上的另一个索引将外围设备组合在一起。这是我在上面SELECT
语句中添加的内容:
(SELECT group_concat(DISTINCT peripheral.peripheral) as peripheral
FROM lookup_peripheral
LEFT OUTER JOIN peripheral ON peripheral.peripheral_id = lookup_peripheral.peripheral_id
WHERE lookup_difficulty.content_id = lookup_peripheral.content_id
GROUP BY lookup_peripheral.content_id
LIMIT 1) as peripheral
我使用了LEFT OUTER
,因为有些条目没有任何外围设备。对于大多数表,对于40k行数据库,400MHz处理器上的总查询时间现在为.02s,具有128MB的100Hz RAM。
EXPLAIN
现在为USING INDEX
表格提供lookup_difficulty
。我添加了这个来实现:
ALTER TABLE `pictuts`.`lookup_difficulty` DROP PRIMARY KEY ,
ADD PRIMARY KEY ( `difficulty_id` , `content_id` )
编辑2 我注意到,通过使用分页进行大偏移,页面加载速度会慢得多。您可能也体验过其他网站。幸运的是,正如Peter Zaitsev所指出的那样,有一种方法可以避免这种情况。这是我更新的片段,用于实现30K或0的偏移的相同时间:
FROM
SELECT lookup_difficulty.content_id, lookup_difficulty.difficulty_id
FROM lookup_difficulty
LIMIT '.$offset.', '.$per_page.'
) ld
现在只需将ld.whatever
添加到每个JOIN
制作中,就可以了!我的查询现在看起来像一团糟,但至少它已经过优化。我认为没有人会在阅读这篇文章时做到这一点......
答案 0 :(得分:2)
输入Justin的答案,所以这个问题没有得到答案:
想出来。我做了我怀疑我必须做的事情,那就是添加一个子查询。由于MYSQL每个表只能使用一个索引,因此我无法将GROUP BY和SORT BY一起用于我的特定设置。相反,我添加了另一个查询,该查询将使用另一个表上的另一个索引将外围设备组合在一起。这是我在上面的SELECT语句中添加的内容:
(SELECT group_concat(DISTINCT p.peripheral) as peripheral
FROM lookup_peripheral lp
LEFT JOIN peripheral p ON p.peripheral_id = lp.peripheral_id
WHERE ld.content_id = lp.content_id
GROUP BY lp.content_id
LIMIT 1) as peripheral
我使用LEFT OUTER,因为有些条目没有任何外围设备。对于大多数表,40k行数据库的400MHz处理器上的总查询时间现在为.02s,带有128MB的100Hz RAM。
EXPLAIN现在为lookup_difficulty表提供了一个USING INDEX。我添加了这个来实现:
ALTER TABLE pictuts.lookup_difficulty DROP PRIMARY KEY ,
ADD PRIMARY KEY ( difficulty_id , content_id )
编辑2我注意到使用分页的大偏移量,页面加载速度会相当慢。您可能也体验过其他网站。幸运的是,Peter Zaitsev指出,有一种方法可以避免这种情况。这是我更新的片段,用于实现30K或0的偏移的相同时间:
FROM
SELECT ld.content_id, ld.difficulty_id
FROM lookup_difficulty ld
LIMIT '.$per_page.' OFFSET '.$offset.'
) ld
现在只需添加ld.w到每个JOIN,你就拥有它!我的查询现在看起来像一团糟,但至少它已经过优化。我认为没有人会在阅读这篇文章时做到这一点......