2016-05-03 24 views
0

私はPRODUCTSというテーブルを持っています。それはの言語のフィールドを持っています。私はlanguage = 'es'のすべての行を、他の言語でtraduction(対応するID)が不足しているものとしてリストしたいと思います。私は次のことを試しました(id_productsは、同じ製品の異なる言語で関連するキーです)。これは非常に遅いです(数千行の秒数):同じテーブルのLEFT JOINの速度 - Mysql

SELECT 
    * 
FROM 
    products AS source 
    LEFT JOIN products AS target ON source.id_products = target.id_products 
    AND source.`language` = 'es' 
    AND target.`language` = 'en' 
WHERE 
    target.id_products IS NULL 
+1

フィールドのインデックスは作成されていますか? – vaso123

+1

テーブルにはどのくらいの行がありますか? products.id_productsとproducts.languageはインデックスに登録されていますか? – DeadEye

+0

私は言うのに非常に恥ずかしいです:いいえ。私はそれを認識していない、私はそれがSQL文字列のためだと思った。今は0.0005秒かかります。ありがとう!! – Cesar

答えて

1

私は、これは表の索引がないために起こっていると思います。

クエリを高速化するインデックス(id_productslanguage)を追加してみてください。

また、あなたは(EXISTS NOTを使用しようとすることができます)ではなく、左の多分それは同様に少し物事をスピードアップします、参加:

SELECT * FROM products t 
WHERE t.language = 'es' 
AND NOT EXISTS(SELECT 1 FROM products s 
       WHERE s.language = 'en' 
        and s.id_products = t.id_products) 
+0

私の考えは、idとcountの出現順にグループ化し、 "lang = es"でフィルタリングすることでした。それで、count = 1のすべての出現はヒットです。しかし、それが速くなるかどうかは分かりません。 – Fildor

+0

インデックスは '(id_products、language)'のコンポジットインデックスであるべきです。 – Barmar

+0

ああ、それは私が言ったことです、私はそれがはっきりしていないことがわかります。 – sagi

1

それがされるインデックス

ベター

INDEX(language, id_products) 

クエリはsourceで始まります。そのためには、language = 'es'に到達する行をtargetにする必要があります。 targetにとっては、索引列がでている順序は関係ありません。

を使用すると、1ミリ秒未満の時間を取得する場合、あなたはおそらく取得しているクエリキャッシュ

によって誤解しないでください。 "クエリキャッシュ"からの回答。テストのために、あなただけのsource列をしたいので、SELECT * ...をやって何の使用、ないtargetからのすべてのNULLsはありません

SELECT SQL_NO_CACHE ... 

やってそれを避けます。したがって、SELECT source.*と言うか、必要な列だけを入力してください。

+0

はい、スピードテストにはSQL_NO_CACHEを使用しました。ありがとうございます。 SQLをほぼ一秒間持っているときにそれを発見するのは簡単です。次の試行で数ミリ秒かかるだけです。 :) – Cesar

1

クエリでフィルタリングを実行する場所に奇妙なことがあります。 ソースが 'es'であるかどうかにかかわらず、すべての製品のリストが表示されます。わかりやすくするために、すべてのON条件をかっこ内に入れることを常にお勧めします。

SELECT * 
    FROM products AS source 
    LEFT JOIN products AS target 
     ON (source.id_products = target.id_products AND target.language = 'en') 
WHERE source.language = 'es' 
    AND target.id_products IS NULL; 

そして、他の点として、あなたはまた、ソースのフィルタリングのための言語のインデックスを必要とし、あなたのtabellがid_productsにも、どのように大規模に応じて、外に。

alter table products add index search_index (language, id_products); 

これを実際に見るには、sql fiddleを参照してください。

+0

いいえ、それは私が欲しいものです。 'en'と 'es'は照会の際に入れ替えられます。原産地はスペイン語で、3,000品目と言いますが、そのうち1,000本しか英語に翻訳されていません。私は2,000の翻訳されていない製品を持っていたい。 – Cesar

+0

私はen/esを変更しましたが、私のポイントはまだ有効です。結合条件のsource.languageでフィルタリングを実行することはできません。 –

+0

私は答えにSQLのフィドルを追加しました。これは元のクエリと提案された変更の違いを示しています。 –

関連する問題