2016-08-05 16 views
0

こんにちは私は製品とカテゴリが3番目のテーブルを使用して多対多の関係を持つ製品カテゴリデータベースを持っています。製品カテゴリ。製品テーブルの周り23K行をぐるぐると内部結合と大規模データセットを使用したMysql GROUP BY最適化

SELECT * FROM products p JOIN product_category pc ON p.id = pc.product_id 
WHERE pc.category_id IN (1,2,3,4,5,6) GROUP BY p.id LIMIT 0,40 

:今、Imは、カテゴリIDの配列で指定されたカテゴリに属する​​すべての製品を取得するために、データベース上でクエリを実行し、次の例を見ることができますproduct_categoryテーブル26k行。

通常、WHERE IN句で使用されるカテゴリIDの配列には、はるかに多くの要素があります。

このクエリでは、300msを使用して結果を取得します。 GROUP BY句を削除すると、クエリでは2msしか結果を取得できません。

select * from `products` inner join `product_category` on `products`.`id` = `product_category`.`product_id` 
     where `product_category`.`category_id` in ('1', '2', '3', '4', '5', '6', '7', 
    '8', '44', '155', '156', '157', '158', '159', '160', '161', '162', '168', '169', '171', '172', '173', '174', '175', '176', 
    '178', '179', '180', '181', '182', '183', '184', '185', '186', '189', '190', '191', '192', '193', '194', '195', '196', 
    '197', '198', '199', '200', '201', '202', '203', '204', '205', '206', '207', '208', '209', '213', '215', '216', '217', 
    '218', '219', '230', '231', '232', '233', 
    '234', '235', '236', '237', '240', '241', 
    '242', '243', '244', '245', '246', '247', 
    '248', '249', '250', '251', '252', '253', 
    '254', '255', '256', '257', '258', '259', 
    '260', '261', '325', '326', '327', '328', 
    '334', '335', '336', '337', '338', '339', '340', '341', '342', '343', '344') and `products`.`is_visible` = '1' 
    group by `product_category`.`product_id` 
    order by `popularity` desc, `popularity` desc limit 40 offset 0 

クエリの説明は次のとおりです。次のよう

Aより完全なクエリがある

最適化する方法があるかどう

Explain of the query

だから、私の質問は特にグループを照会すると、結果が長すぎると結果がロードされません。

+0

集計していないので、代わりに 'DISTINCT p。*'を試してみましたか? – Uueerdo

+0

@Uueerdoはい私は、変更なしで、Select Distinctを使ったクエリは、グループのクエリと同じくらい時間がかかります。ありがとう – asolenzal

+0

あなたはグループで指定しなかったフィールドに常に同じ結果を与えることが保証されていないので、構造によってそのグループを使用するべきではありません。ちょうどあなたが何かをすることができるからといって、あなたがすべきことを意味するわけではありません。また、必要以上のデータ(結合フィールドが繰り返される)を返し、クエリの速度が遅くなるため、結合があるときはSELECT *を使用しないでください。これらの構文の問題はどちらもSQLの反パターンであり、データベースを実際に理解している人が渡すことを試みた場合、コードレビューを実行することになります。 – HLGEM

答えて

0

私がコメントで言ったように、あなたはSELECT DISTINCT p.*で運があるかもしれません。

SELECT * 
FROM `products` 
WHERE id IN (
    SELECT DISTINCT `product_id` 
    FROM `product_category` 
    WHERE `category_id` IN ([category id list]) 
) 
AND `is_visible` = '1' 
ORDER BY `popularity` DESC, `popularity` DESC 
LIMIT 40 OFFSET 0 

または

SELECT p.* 
FROM `products` AS p 
INNER JOIN (
    SELECT DISTINCT `product_id` 
    FROM `product_category` 
    WHERE `category_id` IN ([category id list]) 
) AS pcSmry ON p.id = pcSmry.product_id 
WHERE p.`is_visible` = '1' 
ORDER BY `popularity` DESC, `popularity` DESC 
LIMIT 40 OFFSET 0 

:しかし、私は通常、人々は別のオプションは、サブクエリを使用する代わりに、直接そのように、参加することです...周り DISTINCT遅さを得るために

GROUP BYを使用してご覧ください

編集:これらのいずれのヘルプもない場合は、WHEREおよびONの条件で使用されているフィールドのインデックスを調べることをお勧めします。

関連する問題