2017-01-03 7 views
0

mysqlがクエリを最適化する方法について質問があります。SQLクエリーを作成する方法インデックス範囲スキャンを使用する

select * 
from pp 
where 1 
    and timestamp >= '2016-01-01' and timestamp <= '2017-01-03' 
    and (s = 0 or s is NULL) 
    and (
     from in (select col from Temp) 
     or 
     to in (select col from Temp2) 
    ) 
order by idx desc limit 0, 100; 

Mysqlは、2つのサブクエリが添付されたタイムスタンプでフルインデックススキャンを使用します。

それは後でサブクエリを適用する最初にタイムスタンプに索引レンジ・スキャンを使用していない理由を私は理解していません。

これには特別な理由がありますか? そうでなければ、インデックス範囲のスキャンを使用することはできますか?

答えて

1
SELECT p.* 
    FROM pp AS p 
    LEFT JOIN Temp AS t ON (p.from = t.col) -- leading up to `OR` 
    LEFT JOIN Temp2 AS t2 ON (p.to = t2.col) 
    WHERE p.timestamp >= '2016-01-01' 
     AND p.timestamp < '2017-01-03' -- avoids extra midnight 
     AND (p.s = 0 OR p.s IS NULL)  -- see note 
     AND (t.col IS NOT NULL OR t2.col IS NOT NULL) -- roundabout `OR` 
    ORDER BY p.idx DESC 
    LIMIT 0, 100; 

注: 0ピックまたはsについてはNULL、両方を許可しないでください。こうすることで、これらの指標の一つは、あなたがAND (..OR..)を簡素化した後に(余分な効率化のために使用することができます。

INDEX(s, timestamp) 
INDEX(s, idx) 

あなたはsのための2つの値を保持している場合、彼らはよく、またはかもしれないが

INDEX(timestamp), 
INDEX(idx) 

を持っています有用ではない/使用。

TempTemp2必要

INDEX(col) -- unless `col` is already the `PRIMARY KEY` 

さらに詳しい説明が必要な場合はSHOW CREATE TABLE ppを入力してください。エンジン、データ型、現在のインデックスなどを確認すると便利です。

IN(SELECT ...)のパフォーマンスが低下します。
ORは、最適化が不十分です。 (私はこれを軽減しようとしました。)

0

編集:私はOPのクエリを読み違えていたので、私は次のような答えを与えました。私は彼がそう

`from` in (select col from Temp) 
and 
`to` in (select col from Temp2) 

を求めていたかのように、2と以下のコードが効果的にAND状態を表して参加する答えながら、彼は

`from` in (select col from Temp) 
or 
`to` in (select col from Temp2) 

を求めていました。しかし、回答の中でRick Jamesが訂正したコードはORの表現方法を示していますが、JOINANDを表すためにどのように使用できるかの例として、それをそのまま残しています。


colTempTemp2の両方で一意である場合は、クエリは、(colが一意でない場合、Temp2JOIN (SELECT DISTINCT col FROM Temp) tと同様でJOIN Temp tを置き換える)

SELECT p.* 
    FROM pp p 
    JOIN Temp t 
     ON (p.from = t.col) 
    JOIN Temp2 t2 
     ON (p.to = t2.col) 
    WHERE p.timestamp >= '2016-01-01' 
    AND p.timestamp <= '2017-01-03' 
    AND (p.s = 0 OR p.s IS NULL) 
ORDER BY p.idx DESC LIMIT 0, 100; 

のようになります。確か

、インデックスが同様にスキャンする前に、これは、fromtoにチェックを実行するが、少なくともそれは、各行のための2つのサブクエリを実行しない...

+0

私はこの定式は正しいとは思わない - OPは2つのルックアップの間に「OR」を持つ。効果的に「AND」と言っています。 –

+0

あなたは絶対に正しいです。私はOPの質問を誤解していた。私は私の答えを編集しました。 – Dario

関連する問題