2017-11-27 6 views
0

1つのクエリフィルタを追加してパフォーマンスが低いクエリを1つクエリします。MySQL内部のパフォーマンスを最適化する方法NOT INまたはNOT EXISTSでフィルタリングされたクエリ

`cd`.`categories_id` NOT IN(
     SELECT 
      `p`.`parent_id` 
     FROM 
      `products` `p` 
     WHERE 
      `p`.`product_type` = 'X' 
     AND 
      `p`.`parent_id` = `cd`.`categories_id` 
     GROUP BY `p`.`product_type` 
    ) 

私もNOT EXISTSを使用してもう一つの解決策を試してみてくださいそれは、次のとおりです。私はこのように見えるか追加されたものを1つの新しいフィルタを持って、このクエリ内

SELECT 
    `c`.`categories_id`, 
    `c`.`section_id`, 
    `c`.`categories_status`, 
    IF(`c`.`categories_status` = 1, 'ON', 'OFF') AS `categories_status_name`, 
    TRIM(`cd`.`categories_name`) AS `categories_name`, 
    IF(`cd`.`concert_date` <> '', 
     DATE_FORMAT(STR_TO_DATE(`cd`.`concert_date`,'%d/%m/%Y'),'%d.%m.%Y'), 
     NULL 
    ) AS `concert_date`, 
    TRIM(`cd`.`concert_time`) AS `concert_time` 
FROM 
    `categories` `c` 
    JOIN `categories_description` `cd` ON `c`.`categories_id` = `cd`.`categories_id` 
WHERE 
    `c`.`plan_id` > 2 
AND 
    `c`.`categories_status` = '1' 
AND 
    `cd`.`categories_id` NOT IN(
    SELECT 
     `p`.`parent_id` 
    FROM 
     `products` `p` 
    WHERE 
     `p`.`product_type` = 'X' 
    AND 
     `p`.`parent_id` = `cd`.`categories_id` 
    GROUP BY `p`.`product_type` 
) 
GROUP BY `c`.`categories_id` 
ORDER BY DATE_FORMAT(STR_TO_DATE(`cd`.`concert_date`,'%d/%m/%Y'),'%Y-%m-%d') DESC, `cd`.`categories_name` DESC 

:ここ

がいっぱいクエリです多分悪い:

NOT EXISTS (
    SELECT 
     DISTINCT 1 
    FROM 
     `products` `p` 
    WHERE 
     `p`.`product_type` = 'X' 
    AND 
     `p`.`parent_id` = `cd`.`categories_id` 
    GROUP BY `p`.`product_type` 
) 

私の主な問題は、このフィルタfまたはX製品を含むカテゴリを削除すると、パフォーマンスが悪化することがあります。このフィルタページのロードがなければ、0.5〜0.8秒の範囲になりますが、このフィルタページのロードは8〜10秒です。

このクエリを最適化するお手伝いがありますか?

+0

そのクエリは巨大ではありません;-) – Zim84

+0

OK私は大きくても小さいです:) –

+0

最初にすべてのサブクエリでGROUP BYを排除します。 MySQLが役に立たないと気付かないと、ソートが開始されます。そしてそのDISTINCTも余分です – Ronald

答えて

1

これは機能する可能性があります。ほとんどのエンジンは、内部的に以下のフォームへのクエリを変更しない限り、NOT IN/NOT EXISTSではあまり良くありません。 少なくともそれは試してみる価値があります。

SELECT 
    `c`.`categories_id`, 
    `c`.`section_id`, 
    `c`.`categories_status`, 
    IF(`c`.`categories_status` = 1, 'ON', 'OFF') AS `categories_status_name`, 
    TRIM(`cd`.`categories_name`) AS `categories_name`, 
    IF(`cd`.`concert_date` <> '', 
     DATE_FORMAT(STR_TO_DATE(`cd`.`concert_date`,'%d/%m/%Y'),'%d.%m.%Y'), 
     NULL 
    ) AS `concert_date`, 
    TRIM(`cd`.`concert_time`) AS `concert_time` 
FROM 
    `categories` `c` JOIN `categories_description` `cd` 
        ON `c`.`categories_id` = `cd`.`categories_id` 
    LEFT JOIN `products` `p` 
    ON `p`.`parent_id` = `cd`.`categories_id` 
    AND `p`.`product_type` = 'X' 
WHERE 
    `c`.`plan_id` > 2 
AND 
    `c`.`categories_status` = '1' 
AND 
    `p`.`parent_id` IS NULL 
GROUP BY `c`.`categories_id` 
ORDER BY DATE_FORMAT(STR_TO_DATE(`cd`.`concert_date`,'%d/%m/%Y'),'%Y-%m-%d') DESC, `cd`.`categories_name` DESC 
+0

23行に1つのタイプミスがありますが、これも実行可能です。 @NigelRenのアドバイスを使って良い解決策が1つも得られます –

+0

ありがとうございます。私は欠けているバックティックを加えました。とにかく、違いを構築するには 'p.parent_id is null'をテストする必要があります。厳密に言えば、 'null!= 'X' 'のような条件は真と評価すべきではありませんが、MySQLはこれを別の方法で見ることができます – Ronald

0

ここで私が得た中で最も速い解決法があります。

SELECT 
    `c`.`categories_id`, 
    `c`.`section_id`, 
    `c`.`categories_status`, 
    IF(`c`.`categories_status` = 1, 'ON', 'OFF') AS `categories_status_name`, 
    TRIM(`cd`.`categories_name`) AS `categories_name`, 
    IF(`cd`.`concert_date` <> '', 
     DATE_FORMAT(STR_TO_DATE(`cd`.`concert_date`,'%d/%m/%Y'),'%d.%m.%Y'), 
     NULL 
    ) AS `concert_date`, 
    TRIM(`cd`.`concert_time`) AS `concert_time` 
FROM 
    `categories` `c` 
    INNER JOIN `categories_description` `cd` ON `c`.`categories_id` = `cd`.`categories_id` 
    LEFT JOIN `products` `p` ON `p`.`parent_id` = `cd`.`categories_id` 
WHERE 
    `c`.`plan_id` > 2 
AND 
    `c`.`categories_status` = '1' 
AND `p`.`product_type` != 'X' 
GROUP BY `c`.`categories_id` 
ORDER BY DATE_FORMAT(STR_TO_DATE(`cd`.`concert_date`,'%d/%m/%Y'),'%Y-%m-%d') DESC, `cd`.`categories_name` DESC 

@NigelRenのおかげで、この問題の解決方法がわかります。 @Ronaldはほぼ同じソリューションを提供しますが、私のソリューションよりも少し遅い(0.400秒)です。

ありがとうございました!

関連する問題