2016-11-15 7 views
2

私は現在、ユーザーを表示するために20個のオブジェクトを選択するために5つのテーブルを結合しますが、残念ながらGROUP BYORDER BYを使用すると、遅いMySQLクエリ、グループごとに制限する

クエリの例は次のようになります。クエリのEXPLAIN

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 

がこれを示しています

+------+-------------+-------+--------+----------------------------+------------+---------+---------------------------------------+--------+--------------------------------------------------------+ 
| 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のキーを使用していないようなので、それが見えます、プロファイリングでは、tmpテーブルへのコピーに2.7sが使用されています。

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 | 
+---------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 


+0

私はすべて参加するためにあなたがインデックスを持っていることはよく分からないが、これはグループ化することはまだあなたがそのためのインデックスを持っていた場合でも、遅くなることを意味します。 –

答えて

2

まず最初に、これは非標準のグループです。したがって、mysql 5.7にアップグレードすると動作を停止します。

最大の問題は、objekteテーブルでインデックスが使用されていないことに起因します。さらに悪化させるためには、そのテーブルのレーティングフィールドで注文していますが、インデックスはまだ使用されていません。可能な解決策は、このような複合インデックスを作成することです:

CREATE INDEX objekte_idx ON objekte(id,rating); 
+0

ありがとう、これは私も他の列で私は一度それら(id、評価、minprice)をすべてインデックスを作成しようとしたので、私は2つの別のものを作る必要があります。私はまた別の方法でグループを行うことができるはずです。 – Som1

+0

実際、mysqlはテーブルごとに1つのインデックスしか使用できません。したがって、異なるインデックスを作成してもそれ以上の改善は起こりません。 mysqlを使用すると、複数の列インデックスが使用できますが、列の順序を正しく取得する必要があります。 id、ratingはここで使用されますが、rating、idはそうではありません! – e4c5

0

ここでは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 
+0

私はGROUP BYを使用するので、同じオブジェクトを複数回取得することはありません。オブジェクトはリージョン(または国の地域)の異なるサブリージョンに置くことができます。 それから、私はなぜGROUP BYを必要としないのですか? 0は、より大きな値のプレースホルダです。 – Som1

+0

そのために別のものを使用する –

+0

GROUP BYを削除するだけで助けになるので、不幸にも私から別の間違いがあります。 – Som1

関連する問題