MySQLは、非常に遅いクエリではどこにありますか?

SELECT product_id
FROM ebay_shop
LEFT JOIN amazon_shop ON ebay_shop.product_id = amazon_shop.product_id
WHERE ebay_shop.validated = 2007
AND amazon_shop.validated = 2007

Result(= 150 products): products are validated in ebay_shop && amazon_shop in year 2007

SELECT ebay_shop.product_id
FROM ebay_shop
WHERE ebay_shop.validated = 2010

結果(= 4000製品):2010年にebay_shopで製品の有効性が確認されました

Question: i want to find products which aren't validated to 2010 of 2007 list, products have in 2007 but not in 2010.

私のクエリ:

SELECT product_id
FROM ebay_shop
LEFT JOIN amazon_shop ON ebay_shop.product_id = amazon_shop.product_id
WHERE ebay_shop.validated = 2007
AND amazon_shop.validated = 2007
AND NOT IN (SELECT ebay_shop.product_id
            FROM ebay_shop
            WHERE ebay_shop.validated = 2010)

私のクエリは4000レコードで非常に遅い(~60秒)150を見つける。私はこのクエリを改善するために助けが必要です。

2
EXPLAINの出力は何ですか?テーブルにはどのようなインデックスがありますか?結合およびWHERE句で使用される列のデータ型は何ですか?
追加された 著者 ypercubeᵀᴹ,
注: LEFT JOIN は実際には INNER JOIN です。
追加された 著者 ypercubeᵀᴹ,

3 答え

パフォーマンスではひどいです。おそらく、最良の方法は、あなたの2010年のLEFT JOINを実行し、それがNULLであることを修飾することです。見つかったレコードは、それをスローして、join修飾子を介してNULLを返すレコードをそのまま残します。

さらに、インデックス(validated、product_id)を使用して、YEAR AND PRODUCTに基づいて、eBayショップとアマゾンショップのインデックスを用意してください。すべての共通の年を小規模なものとして維持し、その中のすべての製品を循環させるために、まず年を持つ理由。次に、索引もそれぞれの結合に対して最適化されます。

SELECT STRAIGHT_JOIN
      es.product_id
   FROM 
      ebay_shop eshop
         LEFT JOIN amazon_shop ashop
             ON eshop.validated = ashop.validated
            AND eshop.product_id = ashop.product_id

         LEFT JOIN ebay_shop ebay2
            on ebay2.validated = 2010
           and ebay2.product_id = eshop.product_id
   WHERE 
          eshop.validated = 2007
      and ebay2.validated is null
4
追加された
@ypercube、私の悪い...約11:30昨夜、眼鏡とそれを誤解。
追加された 著者 DRapp,
「すべてのレコードに対してサブセレクションを処理しています」と言っているのはなぜですか?相関サブクエリではありません。
追加された 著者 ypercubeᵀᴹ,

私はこれが本当に答えではなく、別の研究事例であることを認識しています!

私は「NOT IN」を使用しますが、別の状況で使用します。私は約300レコードを持つテーブルの 10秒以上のクエリを取得する結果を得る。

クエリは次のとおりです。

(
SELECT (
'inscrit'
) AS 
TYPE , membre_mandataire.id AS id, membres.prenom AS prenom, membres.nom_de_famille AS nom_de_famille, membre_mandataire.photo AS photo, membre_mandataire.niveau_qualification AS niveau_qualification, membre_mandataire.numero_mandataire AS numero_mandataire
FROM membres, membre_mandataire
WHERE membre_mandataire.id_membre = membres.id
AND membre_mandataire.confirme = 'Y'
AND membre_mandataire.visible_dans_liste = 'Y'
)
UNION (

SELECT (
'actif'
) AS 
TYPE , mandataires_actifs.id AS id, mandataires_actifs.prenom AS prenom, mandataires_actifs.nom_de_famille AS nom_de_famille, mandataires_actifs.photo AS photo, mandataires_actifs.niveau_qualification AS niveau_qualification, mandataires_actifs.numero_mandataire AS numero_mandataire
FROM mandataires_actifs, membre_mandataire
WHERE (
mandataires_actifs.numero_mandataire
) NOT 
IN (

SELECT membre_mandataire.numero_mandataire
FROM membre_mandataire
WHERE membre_mandataire.confirme = 'Y'
AND membre_mandataire.visible_dans_liste = 'Y'
)
)
ORDER BY nom_de_famille ASC

フィールド "numero_mandataire"は、両方のテーブルの定数です。結果では、テーブル membre_mandataire のすべてのレコードとUNIONまたはすべてのレコードを「numero_mandataire」がテーブル mandataires_actifs に見つからない場合はJOINする必要があります。

私は私の解決策は "UNION"の代わりに "LEFT JOIN"を使うことになると思うが、私はまだ "NOT IN"に固執している。私はしばらくの間試してきましたが、私はそれを動作させることはできません。

私はMySQLを学んでいるが、私はまだそこにいないように見える!

助けてくれてありがとう!

  • Blaise
1
追加された

@DRappは素晴らしい回避策を書いており、私は他のアイデアを追加したい...

SELECT group_concat(product_id)
FROM ebay_shop 
LEFT JOIN amazon_shop ON ebay_shop.product_id = amazon_shop.product_id 
WHERE ebay_shop.validated = 2007 
AND amazon_shop.validated = 2007 

その後:

SELECT product_id    
FROM ebay_shop    
LEFT JOIN amazon_shop ON ebay_shop.product_id = amazon_shop.product_id    
WHERE ebay_shop.validated = 2007    
AND amazon_shop.validated = 2007    
AND NOT IN (1,2,3,4)    /* results from first query */
0
追加された