2016-03-31 1 views
1

に参加:d.id(PRIMARY)上のインデックス、d.added_time、dt.datum_idがあり日付範囲でのMySQLのクエリの最適化と、私は次のクエリ持っ

SELECT COUNT(*) 
    FROM datum d 

    JOIN datum_type dt 
    ON dt.datum_id = d.id 
    AND dt.type_id = '3' 

WHERE d.added_time >= DATE_FORMAT(CURDATE(), '%Y-%m') 
    AND d.added_time < DATE_FORMAT(CURDATE() + INTERVAL 1 MONTH, '%Y-%m') 

をして

をdt.type_id説明現在の計画では、次のとおりです。私たちはかなりの時間のための基準レコードを持っていたよう

+----+-------------+-------+--------+--------------------+---------+---------+-------------+--------+-------------+ 
| id | select_type | table | type | possible_keys | key | key_len |  ref  | rows | Extra | 
+----+-------------+-------+--------+--------------------+---------+---------+-------------+--------+-------------+ 
| 1 | SIMPLE  | dt | ref | type_id,datum_id | type_id |  1 | const  | 602628 |    | 
| 1 | SIMPLE  | d  | eq_ref | PRIMARY,added_time | PRIMARY |  8 | dt.datum_id |  1 | Using where | 
+----+-------------+-------+--------+--------------------+---------+---------+-------------+--------+-------------+ 

は、それが最初datum.id PRIMARYを使用して、それぞれが基準かどうかを確認するために、行に参加したスキャンタイプに加入しているように見えます。 added_timeはwです範囲内で。

私はadded_timeインデックスを使用してみましたが、計画はした説明:ほとんど限りdatum.added_timeの範囲内の異なるdatum_type.type_idのように多くのdatum_typesがあるので取り

+----+-------------+-------+-------+------------------+------------+---------+------+---------+--------------------------+ 
| id | select_type | table | type | possible_keys | key  | key_len | ref | rows |   Extra   | 
+----+-------------+-------+-------+------------------+------------+---------+------+---------+--------------------------+ 
| 1 | SIMPLE  | d  | index | added_time  | added_time |  4 | NULL | 6195194 | Using where; Using index | 
| 1 | SIMPLE  | dt | ref | type_id,datum_id | datum_id |  8 | d.id |  1 | Using where    | 
+----+-------------+-------+-------+------------------+------------+---------+------+---------+--------------------------+ 

これをスピードアップするインデックスの組み合わせはありますか?

+0

(datum_id、type_id)で複合キーを試しましたか?私は実際にDATE_FORMATビットを理解していませんが、パフォーマンスにはほとんど影響しません。 – Strawberry

+0

おっと、インデックスを試してみます。 – Arth

+0

'datum_type'の不要な正規化? –

答えて

1

added_timedatetimeまたはdateとします。次に、条件を文字列として表現する必要があります。これはdatum(added_time, id)datum_type(datum_id, type_id)にインデックスを利用することができます

SELECT COUNT(*) 
FROM datum d JOIN 
    datum_type dt 
    ON dt.datum_id = d.id AND 
     dt.type_id = '3' 
WHERE d.added_time >= DATE_SUB(CURDATE(), INTERVAL DAY(CURDATE()) - 1 DAY) AND 
     d.added_time < DATE_ADD(DATE_SUB(CURDATE(), INTERVAL DAY(CURDATE()) - 1 DAY), INTERVAL 1 MONTH); 

:代わりに、date定数を使用します。

datum_typeから来る(カウント用)は、重複レコードが存在しない場合、私はあなたのようにクエリを書き直すことを示唆している:type_idが整数である場合、あなたは、単一引用符をドロップする必要があります

SELECT COUNT(*) 
FROM datum d 
WHERE d.added_time >= DATE_SUB(CURDATE(), INTERVAL DAY(CURDATE()) - 1 DAY) AND 
     d.added_time < DATE_ADD(DATE_SUB(CURDATE(), INTERVAL DAY(CURDATE()) - 1 DAY), INTERVAL 1 MONTH) AND 
     EXISTS (SELECT 1 
       FROM datum_type dt 
       WHERE dt.datum_id = d.id AND dt.type_id = '3' 
      ); 

。 SQLで異なるデータ型を混在させると、索引の最適化と混乱を招くことがあります。

+0

日付範囲が鉱山と同じではない、現在の暦月が必要で、オプティマイザに問題がないようです。 'DATE_FORMAT()'を使わずにより良い方法があれば、私はうれしくそれを書き直そうと思います!私は他の提案を試みるでしょう。 – Arth

+0

私は、 'date + INTERVAL expr unit'構文を使用するように変更しましたが、あなたの範囲はうまくいきました。興味深いことに、 'DATE_FORMAT(CURDATE()、 '%Y-%m')'を 'DATE_FORMAT(CURDATE()、 '%Y-%m-01')'に変更し、また働いた。 – Arth

+0

インデックスを 'added_time'に追加すると、'(added_time、PRIMARY) 'が無料で得られると思いますので、最後には必要ありませんでした。 – Arth