[英]Slow MySQL Query, Group By Order By Limit
我目前加入5個表來選擇20個對象來顯示用戶,不幸的是,如果我使用GROUP BY
和ORDER BY
它變得非常慢。
示例查詢看起來像這樣:
SELECT r.name, l.name, o.typ, o.id, persons, children, description, rating, totalratings, minprice, picture FROM angebote as a
JOIN objekte as o ON a.fid_objekt = o.id
JOIN regionen as r ON a.fid_region = r.id
JOIN laender as l ON a.fid_land = l.id
WHERE l.slug="aegypten" AND a.letztes_angebot >= 1
GROUP BY a.fid_objekt ORDER BY rating DESC LIMIT 0,20
查詢的EXPLAIN顯示:
+------+-------------+-------+--------+----------------------------+------------+---------+---------------------------------------+--------+--------------------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+-------+--------+----------------------------+------------+---------+---------------------------------------+--------+--------------------------------------------------------+
| 1 | SIMPLE | l | ref | PRIMARY,slug | slug | 767 | const | 1 | Using index condition; Using temporary; Using filesort |
| 1 | SIMPLE | o | ALL | PRIMARY | NULL | NULL | NULL | 186779 | Using join buffer (flat, BNL join) |
| 1 | SIMPLE | a | ref | unique_key,letztes_angebot | unique_key | 8 | ferienhaeuser.o.id,ferienhaeuser.l.id | 1 | Using where |
| 1 | SIMPLE | r | eq_ref | PRIMARY | PRIMARY | 4 | ferienhaeuser.a.fid_region | 1 | |
+------+-------------+-------+--------+----------------------------+------------+---------+---------------------------------------+--------+--------------------------------------------------------+
因此看起來它沒有使用表objekte
的密鑰,Profiling說它使用2.7s來復制到tmp表。
而不是FROM angebote
或JOIN objekte
我嘗試了它(SELECT * GROUP BY id)
但遺憾的是這沒有改進。
用於WHERE
, ORDER BY
和GROUP BY
的字段也被編入索引。
我想我在這里錯過了一些基本概念,任何幫助將不勝感激。
因為我最有可能在表格中犯了錯誤,這里描述了它們:
Objekte
+---------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | objekte | CREATE TABLE `objekte` ( `id` int(11) NOT NULL, `typ` varchar(50) NOT NULL, `persons` int(11) NOT NULL, `children` int(11) NOT NULL, `description` text NOT NULL, `rating` float NOT NULL, `totalratings` int(11) NOT NULL, `minprice` float NOT NULL, `picture` varchar(255) NOT NULL, `last_offer` int(11) NOT NULL, PRIMARY KEY (`id`), KEY `minprice` (`minprice`), KEY `rating` (`rating`), KEY `last_offer` (`last_offer`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 | +---------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
Angebote
+-----------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | angebote | CREATE TABLE `angebote` ( `id` int(11) NOT NULL AUTO_INCREMENT, `fid_objekt` int(11) NOT NULL, `fid_land` int(11) NOT NULL, `fid_region` int(11) NOT NULL, `fid_subregion` int(11) NOT NULL, `letztes_angebot` int(11) NOT NULL, PRIMARY KEY (`id`), UNIQUE KEY `unique_key` (`fid_objekt`,`fid_land`,`fid_region`,`fid_subregion`), KEY `letztes_angebot` (`letztes_angebot`), KEY `fid_objekt` (`fid_objekt`), KEY `fid_land` (`fid_land`), KEY `fid_region` (`fid_region`), KEY `fid_subregion` (`fid_subregion`) ) ENGINE=InnoDB AUTO_INCREMENT=2433073 DEFAULT CHARSET=utf8 | +-----------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
laender,regionen,subregionen(相同結構)
+---------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | laender | CREATE TABLE `laender` ( `id` int(11) NOT NULL AUTO_INCREMENT, `iso` varchar(2) NOT NULL, `name` varchar(255) NOT NULL, `slug` varchar(255) NOT NULL, `letztes_angebot` int(11) NOT NULL, PRIMARY KEY (`id`), UNIQUE KEY `iso` (`iso`), KEY `slug` (`slug`), KEY `letztes_angebot` (`letztes_angebot`) ) ENGINE=InnoDB AUTO_INCREMENT=107 DEFAULT CHARSET=utf8 | +---------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
首先,這是一個非標准組。 因此,當您升級到mysql 5.7時它將停止工作。
最大的問題來自objekte
表上沒有使用索引的事實。 更糟糕的是,您要在該表的評級字段中進行排序,但索引仍未使用。 一種可能的解決方案是創建一個這樣的復合索引:
CREATE INDEX objekte_idx ON objekte(id,rating);
您不需要在這里使用GROUP BY。 您還沒有使用聚合函數。 因此從查詢中刪除GROUP BY。 刪除Group By將提高查詢性能。 也無需為限制定義0。
SELECT r.name, l.name, o.typ, o.id, persons, children, description, rating, totalratings, minprice, picture FROM angebote as a
JOIN objekte as o ON a.fid_objekt = o.id
JOIN regionen as r ON a.fid_region = r.id
JOIN laender as l ON a.fid_land = l.id
WHERE l.slug="aegypten" AND a.letztes_angebot >= 1
ORDER BY rating DESC LIMIT 20
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.