1

最適化したい非常に大規模なクエリがあります。これは、1つのテーブル要求と5つのテーブル左結合で構成されています。このクエリは完了するのに0.3428秒かかります(結果:合計4,340秒、クエリは0.3428秒かかりました)私は約10000のエントリを処理していますが、これは間違いなく大きくなります。

現在、それ自体によるクエリは問題ではなく、最大の問題はINステートメントです。

  1. 2つのINステートメントがあります
  2. 両方ともWHEREステートメントにあります
  3. この特定のページの読み込みでは、両方に大量のID、3344個のIDエントリがあります。例:(99、1、5、8458、...)
  4. 両方のINステートメントには、3344 IDの同じセットが含まれます。例:((cf.catid IN(99、1、5、8458、...)AND cf.cid = c.id)OR p.category IN(99、1 、5、8458、...))

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

SELECT 
    p.id, c.id AS pCid, c.name AS cName, p.name, p.seo, 
    p.description AS pDescription, cd.description,
    p.category, p.archive, cf.catid, cf.pid, p.order_nr, 
    c.order_nr AS cOrder, c.seo AS cSeo, cat.name AS catName, 
    cat.order_id, pr.price, pr.sale_price, pr.sale_expiry,
    IF( pr.sale_price > 0, pr.sale_price, pr.price ) AS `oPrices`,
    pr.member_price, p.`set`, p.get_the_look,
    c.from_text_price, c.thumb, c.code AS colour_code, 
    p.code AS product_code, p.supplier_part_number, 
    p.oem_part_number, p.make, p.model, p.year, p.sub_model
FROM 
    products p
    LEFT JOIN category_featured cf ON p.id=cf.pid
    LEFT JOIN colours c ON c.pid=p.id
    LEFT JOIN colour_descriptions cd ON c.id=cd.colour_id
    LEFT JOIN category cat ON cat.id=p.category
    LEFT JOIN pricing pr ON pr.cid=c.id
WHERE 
    (
        (cf.catid IN ( .. 3344 ID entries .. ) AND cf.cid=c.id) OR p.category IN ( .. 3344 ID entries .. )
    )
    AND p.archive='0'

    AND p.status='1' AND c.status='1' 
    AND c.archive='0'
    AND cat.status IN (1,2)

GROUP BY `c`.`id`
ORDER BY `oPrices` DESC

INステートメントを使用してテーブル内の特定のIDをチェックする、または別のチェックをすべて一緒に使用するより良い方法はありますか?

ここでの主な問題は速度です。可能な限り最高のパフォーマンスを実現したいと考えています。

これまでのところ、私が行ったことと、いくつかの設定がどのように設定されているか:

  • これらのテーブルのインデックスを作成しました(このクエリで使用されるINT(整数)の列のみにインデックスがあります)
  • 一部のテーブルはMyISAMであり、一部はInnoDBです(クエリで使用されない他のテーブルは、クエリに含まれるいくつかのテーブルと関係があるため、InnoDBである必要があります)
  • クエリ内のテーブル間に関係はありません
  • クエリを実行するには、PHPとMySQLIを使用します

ありがとう

アップデート!!!!

IFステートメントを使用して作成した新しい列のクエリが非常に遅い理由に気付きましたoPrices。次に、「ORDER BY oPricesDESC」を使用するとクエリが遅くなります。削除すると、クエリにかかる時間は0.00009秒です。これは驚くべきことです。 !!しかし、今では正しく順序付けられたデータを取得できず、PHPで順序付けを行ったとしても、理想的ではない新しいページネーション関数を作成する必要があります。

4

1 に答える 1

2

INインデックス使用されていない可能性があるため、クエリの最適化が非常に困難になる可能性があります(これはを使用して確認できますEXPLAIN)。別のアプローチは、これらのIDを一時テーブルにロードしてから、を実行することJOINです。

このリンクから:

http://explainextended.com/2009/08/18/passing-parameters-in-mysql-in-list-vs-temporary-table/

パラメータの大きなリストの場合、それらを一時テーブルに渡す方が定数リストよりもはるかに高速ですが、小さなリストの場合、パフォーマンスはほぼ同じです。

一時テーブルを使用することは、MySQLでパラメータの大きな配列を渡すための最良の方法です。

于 2012-09-19T15:58:54.613 に答える