次のクエリがあります。
SELECT `p_products`.`id`, `p_products`.`name`, `p_products`.`date`,
`p_products`.`img`, `p_products`.`safe_name`, `p_products`.`sku`,
`p_products`.`productstatusid`, `op`.`quantity`
FROM `p_products`
INNER JOIN `p_product_p_category`
ON `p_products`.`id` = `p_product_p_category`.`p_product_id`
LEFT JOIN (SELECT `p_product_id`,`order_date`,SUM(`product_quantity`) as quantity
FROM `p_orderedproducts`
WHERE `order_date`>='2013-03-01 16:51:17'
GROUP BY `p_product_id`) AS op
ON `p_products`.`id` = `op`.`p_product_id`
WHERE `p_product_p_category`.`p_category_id` IN ('15','23','32')
AND `p_products`.`active` = '1'
GROUP BY `p_products`.`id`
ORDER BY `date` DESC
説明は次のように述べています。
id select_type テーブル タイプ possible_keys キー key_len ref 行 エクストラ 1 PRIMARY p_product_p_category ref p_product_id,p_category_id,p_product_id_2 p_category_id 4 const 8239 一時的な使用; ファイルソートの使用 1 PRIMARY p_products eq_ref PRIMARY PRIMARY 4 pdev.p_product_p_category.p_product_id 1 where の使用 1 プライマリ すべて NULL NULL NULL NULL 78 2 DERIVED p_orderedproducts index order_date p_product_id 4 NULL 201 where の使用
また、p_products.date を含む多数の列にインデックスを作成しています。
問題は、多数のカテゴリに 5000 を超える製品がある場合の速度です。60000 個の製品に 1 秒以上かかります。物事をスピードアップする方法はありますか?
これは、左結合を削除した場合にも当てはまります。その場合、結果は次のようになります。
id select_type テーブル タイプ possible_keys キー key_len ref 行 エクストラ 1 SIMPLE p_product_p_category インデックス p_product_id,p_category_id,p_product_id_2 p_product_id_2 8 NULL 91167 where; を使用。インデックスの使用; 一時的な使用; ファイルソートの使用 1 SIMPLE p_products eq_ref PRIMARY PRIMARY 4 pdev.p_product_p_category.p_product_id 1 where の使用
中間テーブル p_product_p_category には、p_product_id と p_category_id の両方のインデックスと、両方を組み合わせたインデックスがあります。
オチの提案を試してみると、次のようになりました。
id select_type テーブル タイプ possible_keys キー key_len ref 行 エクストラ 1 PRIMARY ALL NULL NULL NULL NULL 62087 一時的な使用。ファイルソートの使用 1 PRIMARY nr1media_products eq_ref PRIMARY PRIMARY 4 cats.nr1media_product_id 1 where の使用 2 派生 nr1media_product_nr1media_category 範囲 nr1media_category_id nr1media_category_id 4 NULL 62066 where の使用
カテゴリの中間テーブルで製品を結合して、選択したカテゴリのすべての固有の製品を日付でソートして取得するにはどうすればよいかという質問を単純化できると思います。
編集:
これにより、順序付けやグループ化に一時テーブルを使用せずに、カテゴリ内のすべての一意の製品が得られます。
SELECT
`p_products`.`id`,
`p_products`.`name`,
`p_products`.`img`,
`p_products`.`safe_name`,
`p_products`.`sku`,
`p_products`.`productstatusid`
FROM
p_products
WHERE
EXISTS (
SELECT
1
FROM
p_product_p_category
WHERE
p_product_p_category.p_product_id = p_products.id
AND p_category_id IN ('15', '23', '32')
)
AND p_products.active = 1
ORDER BY
`date` DESC
上記のクエリは非常に高速で、group by order by (0.04 VS 0.7 秒) を使用した結合よりもはるかに高速ですが、一時テーブルなしでこのクエリを実行できる理由はわかりません。
私は、orderedproducts 結合の別の解決策を見つける必要があると思いますが、それでもクエリが 1 秒以上遅くなります。cron を作成して、販売された製品のランキングを毎晩 1 回更新し、その情報を p_products テーブルに保存します。
誰かが決定的な解決策を持っていない限り...