2017-07-28 5 views
1

私は非常に単純なクエリを持っています(greatest-n-per-groupの状況でサブクエリとして使用されています)。 state_idがプライマリキーです。他はすべて一意ではありません。グループ単位の最大n個のサブクエリで範囲フィルタを使用すると、パフォーマンスが非常に悪くなります。

SELECT max(states.state_id) AS max_state_id 
FROM states 
WHERE states.created >= '2017-06-10 21:53:38.977455' 
    AND states.created < '2017-06-26 07:00:00' 
GROUP BY states.entity_id; 

問題があり、このクエリは恐ろしく遅いです、と私は複数列のインデックスの任意の順序はそれにそれが書かれている方法を解決することができるとは思いません。我々はここで何をしようとして、2つのタイムスタンプ間にentity_idの最新state_idを取得している:それははっきりしていない場合、それは常にusing where; using index; using temporary; using filesort

で終わります。

代わりにmax(states.created)max(states.state_id)ではなく)を使用してください。これはおそらくもっと良い方法ですが、外部クエリに参加するためのstate_idはありません。ここで

は完全なコンテキストを与えるために、外側の部分を含む完全なクエリです:ルースインデックススキャンを行うには、インデックスを許可するよう

SELECT states.state_id AS states_state_id, states.domain AS states_domain, states.entity_id AS states_entity_id, states.state AS states_state, states.attributes AS states_attributes, states.event_id AS states_event_id, states.last_changed AS states_last_changed, states.last_updated AS states_last_updated, states.created AS states_created 
FROM states INNER JOIN (
    SELECT max(states.state_id) AS max_state_id 
    FROM states 
    WHERE states.created >= '2017-06-10 21:53:38.977455' AND states.created < '2017-06-26 07:00:00' GROUP BY states.entity_id 
) AS anon_1 ON states.state_id = anon_1.max_state_id; 

は確かに、このような方法で、この問合せをリライトする方法が必要...このクエリの

+0

外部クエリに他のすべての列が含まれているのはなぜですか?また、あなたの 'MAX'クエリは、より高い' state_id'が後で作成されたということを意味しない場合、間違っている可能性があります。 –

+0

@FelixPamittan:外部クエリは、単にアプリケーションが必要とする値を返すだけです。簡潔にするため、すべてを 'select * 'に置き換えることができます。作成されたvs state_idに関しては、私は同意し、私はそれを私の質問で述べました。しかし、私たちがstate_idの最大値を取得しない場合、私は外側のクエリがそれにどのように結合するのかはわかりません – OverloadUT

+0

すべての'entity_id 'に対して同じ期間をクエリしていますか? – Horaciux

答えて

0

まず、:

SELECT max(s.state_id) AS max_state_id 
FROM states s 
WHERE s.created >= '2017-06-10 21:53:38.977455' AND 
     s.created < '2017-06-26 07:00:00' 
GROUP BY s.entity_id; 

私はあなたがstates(created, entity_d, state_id)にインデックスを持っていることを確認したいと思います。それが助けになるかどうかだけ見てください。

第二には、としてクエリを書き直す考えてみます。states(entity_id, created, state_id)states(created, entity_id, state_id)(インデックス事項の列の順序):このクエリの

SELECT max(s.state_id) AS max_state_id 
FROM states s 
WHERE s.created >= '2017-06-10 21:53:38.977455' AND 
     s.created < '2017-06-26 07:00:00' AND 
     s.state_id = (SELECT MAX(s2.state_id) 
        FROM states s2 
        WHERE s2.entity_id = s.entity_id AND 
          s2.created >= '2017-06-10 21:53:38.977455' AND 
          s2.created < '2017-06-26 07:00:00' 
        ); 

、あなたは上のインデックスをしたいです。

+0

残念ながら、最初のインデックスは機能しません。問題は、2番目のディメンションが、3番目のディメンションの集計関数でグループ化されていない_range_フィルタであることです。これにより、現在のクエリの記述方法でインデックスを使用することは不可能になります。クエリの書き換えについては、私はそれをテストしています... – OverloadUT

+0

さて、その2番目のクエリは動作していないようです。私は実際に何をしようとしているのか分かりません。私は指数なしで13時間稼働していると言えますが、それはインデックスでパフォーマンスを得ることができても、私には怪しいと感じますか? – OverloadUT

関連する問題