解決見下文索引與GROUP BY,ORDER BY,和GROUP_CONCAT
我試圖同時使用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
因爲某些條目沒有任何外設。對於大多數表格,400MHz處理器上的總查詢時間現在爲.02s,對於40k行數據庫,具有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 lookup_difficulty.content_id, lookup_difficulty.difficulty_id
FROM lookup_difficulty
LIMIT '.$offset.', '.$per_page.'
) ld
現在只需加ld.whatever
每JOIN
製成,有你有它!我的查詢看起來像是一團糟,但至少它已經過優化。我想沒有人會做這麼遠在讀這...
請考慮在下面發佈您的解決方案作爲答案。這樣你可以將問題標記爲已回答。 – Wolph
我不能等到8個小時了...... – Justin
@Justin,現在8小時了。 – Johan