EC-CUBE MYSQLでの速度改善02
date_range
- ENGINEER
SQL_CALC_FOUND_ROWSで高速化
EC-CUBEの一覧では 、
```sql SELECT COUNT(*) FROM ?? WHERE ??? = ??? AND ..
のような形で全体の件数を取得した後、LIMITとOFFSETを確定させてデータを取得するようになっています。
MYSQLの場合、WHEREで絞り込んだ結果でCOUNT(*)を行うと速度がかなり遅いということがあります。
SELECT COUNT(*) FROM dtb_products WHERE del_flg = 0 AND status = 1 AND EXISTS( SELECT * FROM dtb_product_categories WHERE category_id IN (1,2,3,4,5) )
で、全体の件数を取得してから
SELECT * FROM dtb_products WHERE del_flg = 0 AND status = 1 AND EXISTS( SELECT * FROM dtb_product_categories WHERE category_id IN (1,2,3,4,5) ) LIMIT 20 OFFSET 20 ```
取得したいデータを取るクエリを発行しています。 おそらくPostgresqlと合わせる為にこのような形になっていると思うんですが、 MYSQLのみに限定すればSQL_CALC_FOUND_ROWSという便利な関数があります。
それを使う事で多少なりとも速度を速くする事ができます。
使い方は
SELECT
SQL_CALC_FOUND_ROWS
*
FROM
dtb_products
WHERE
del_flg = 0 AND
status = 1 AND
EXISTS(
SELECT
*
FROM
dtb_product_categories
WHERE
category_id IN (1,2,3,4,5)
)
LIMIT 20 OFFSET 20
こんな形で先に取得したいデータを取っておいて、 その後に
SELECT FOUND_ROWS();
を実行で全件取得できます。
これを行うことで重たい処理が1回で済むことになるので、 負荷的にはほぼ半分くらいになります。
件数によって何がいいかは変わりますが、ECくらいの件数だとSQL_CALC_FOUND_ROWSを使用する方が早いと思います。 ちなみにPostgresqlはこの関数は使用できません。
ECサイトを運営する場合、
商品一覧やレビュー一覧、マイページの購入履歴一覧等で使用すると効果的です。
実際はカスタマイズによって検索する項目等も変更の場合がありますが、 負荷の高いと思われるクエリに関してはきっちりINDEXを有効的に張って 速度の事も考えたうえで実装するのがいいかと思います。
速度改善の依頼はこちらから。