2

これを最適化する方法は?

SELECT e.attr_id, e.sku, a.value

FROM product_attr AS e, product_attr_text AS a

WHERE e.attr_id = a.attr_id
AND value
IN (
    SELECT value
    FROM product_attr_text 
    WHERE attribute_id = (
        SELECT attribute_id
        FROM eav_attr 
        WHERE attribute_code = 'similar_prod_id' 
    ) 
    AND value != ''

    GROUP BY value
    HAVING (COUNT( value ) > 1 )
)
4

7 に答える 7

2
SELECT  e.attr_id, e.sku, a.value
FROM    (
        SELECT  pat.value
        FROM    eav_attr ea
        JOIN    product_attr_text pat
        ON      pat.attribute_id = ea.attribute_id
        WHERE   ea.attribute_code = 'similar_prod_id'
                AND value <> ''
        GROUP BY
                value
        HAVING  COUNT(*) > 1
        ) q
JOIN    product_attr_text AS a
ON      a.value = q.value
JOIN    product_attr AS e
ON      e.attr_id  = a.attr_id

インデックスを作成します。

 eav_attr (attribute_code)
 product_attr_text (attribute_id, value)
 product_attr_text (value)
 product_attr (attr_id)
于 2010-10-28T12:17:48.343 に答える
1

注意:EAV(エンティティ、属性、値)テーブルデザインを使用するデザインには注意してください。参照整合性とクエリの複雑さのために、処理が非常に困難になる傾向があります。

以下を使用して最適化します。

  • 副選択の代わりに参加します。
  • 表記に参加します。
  • すべての列名の明示的なテーブルエイリアス。

フェーズ1:

SELECT e.attr_id, e.sku, a.value
  FROM product_attr AS e JOIN product_attr_text AS a
       ON e.attr_id = a.attr_id
 WHERE a.value IN (
          SELECT p.value
            FROM product_attr_text AS p
            JOIN eav_attr AS v ON p.attribute_id = v.attribute_id
           WHERE v.attribute_code = 'similar_prod_id'
             AND p.value != ''
           GROUP BY value
          HAVING (COUNT( value ) > 1)
          )

フェーズ2:

SELECT e.attr_id, e.sku, a.value
  FROM product_attr AS e
  JOIN product_attr_text AS a ON e.attr_id = a.attr_id
  JOIN (SELECT p.value
          FROM product_attr_text AS p
          JOIN eav_attr AS v ON p.attribute_id = v.attribute_id
         WHERE v.attribute_code = 'similar_prod_id'
           AND p.value != ''
         GROUP BY value
        HAVING (COUNT( value ) > 1)
       ) AS x ON x.value = a.value
于 2010-10-28T12:27:15.337 に答える
1

2番目の内部選択を結合に変更します。

SELECT e.attr_id, e.sku, a.value
FROM product_attr AS e, product_attr_text AS a
WHERE e.attr_id = a.attr_id
AND value
IN (
    SELECT at.value
    FROM product_attr_text at, eav_attr eat 
    WHERE at.attribute_id = eat.attribute_id 
          AND eat.attribute_code = 'similar_prod_id' 
          AND value != ''
    GROUP BY value
    HAVING (COUNT( value ) > 1 )
)

次に、実行プランを調べて、クエリがどのように解決されるかを確認します。その実行プランに基づいて追加の最適化が必要になる場合があります(たとえば、attribute_idフィールドにインデックスが付けられていることを確認してください)。

于 2010-10-28T12:16:09.003 に答える
1

JOINに変更します。MySQLはIN()句のサブクエリを適切に最適化しません-行ごとに再計算されます(多くの行で非常に非効率的です)

SELECT e.attr_id, e.sku, a.value
FROM product_attr AS e
INNER JOIN product_attr_text AS a ON e.attr_id = a.attr_id
INNER JOIN (SELECT value
    FROM product_attr_text 
    INNER JOIN eav_attr ON eav_attr.attribute_id=product_attr_text.attribute_id
    WHERE attribute_code = 'similar_prod_id'  
    AND value != ''
    GROUP BY value
    HAVING COUNT( value ) > 1 
) AS filter ON filter.value=a.value

クエリを変換した後(スキーマに応じていくつかの修正が必要になる場合があります)、EXPLAINクエリを実行し、それに応じてインデックスを作成します。

于 2010-10-28T12:16:50.767 に答える
1

フレデリクの答えは正しいですが、私はいくつかのポイントを提案したいと思います:

  • INを避け、代わりにEXISTSを使用してください
  • 回避=(sometableから何かを選択)、代わりに使用が存在します
  • 役に立たないグループ
  • from句で複数のテーブルの代わりに内部結合を使用する

ただし、これもマシン/ dbms /バージョンなどによって異なります。最高のパフォーマンスを得るには、さまざまな実行プランを比較する必要があります。

于 2010-10-28T12:17:14.253 に答える
1

答えにくい...

私が言える唯一のことは:

  • 実行計画を見てください

  • IO 統計を使用します。

ステートメントのどの部分が問題で、その理由を見てください。インデックスを追加するなどしてパフォーマンスを改善できるかどうかを確認してください...

その次に、なぜ group by 句を使用しているのかわかりません...

そして、テーブルを結合する代わりにサブクエリを使用するのはなぜですか? (ただし、SQL Server オプティマイザは同じ実行計画を生成するのに十分なほどスマートである必要があるため、大きな違いはないと思います)。

于 2010-10-28T12:10:21.137 に答える
0

グループの派生テーブルを使用するには、...を使用して、結果を埋める必要のあるテーブルに結合します。

于 2010-10-28T12:16:56.147 に答える