2016-04-04 24 views
2

この私のテーブル:日付columとtest_logにインデックス化され最適化MySQLのクエリ

SELECT d.date, COUNT(l.id) 
FROM test_dates d 
LEFT JOIN test_log l ON l.timest>=d.date AND l.timest<d.date + INTERVAL 1 DAY 
GROUP BY d.date 

テーブルtest_datesを:

CREATE TABLE IF NOT EXISTS `test_dates` (
    `date` date NOT NULL 
) ENGINE=InnoDB DEFAULT CHARSET=utf8; 

CREATE TABLE IF NOT EXISTS `test_log` (
    `id` int(10) unsigned NOT NULL, 
    `timest` datetime NOT NULL 
) ENGINE=InnoDB DEFAULT CHARSET=utf8; 

ALTER TABLE `test_dates` 
    ADD PRIMARY KEY (`date`); 

ALTER TABLE `test_log` 
    ADD PRIMARY KEY (`id`), 
    ADD KEY `emissione` (`timest`); 

私は、日付ごとにログをカウントするには、このクエリを持っています表はタイム・スタンプの列で索引付けされます。

しかし、このクエリを説明すると、クエリの種類が「すべて」でNULLキーが得られました。

+-----+--------------+--------+-------------+--------+----------------+----------+----------+------+--------+-----------+------------------------------------------------+--+ 
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered |      Extra      | | 
+-----+--------------+--------+-------------+--------+----------------+----------+----------+------+--------+-----------+------------------------------------------------+--+ 
| 1 | SIMPLE  | d  | NULL  | index | PRIMARY  | PRIMARY | 3  | NULL | 705 | 100.00 | Using index         | | 
| 1 | SIMPLE  | l  | NULL  | ALL | emissione  | NULL  | NULL  | NULL | 98256 | 100.00 | Range checked for each record (index map: 0x2) | | 
+-----+--------------+--------+-------------+--------+----------------+----------+----------+------+--------+-----------+------------------------------------------------+--+ 

なぜテーブルインデックスを使用できないのですか?

ログテーブルは約100000行あり、クエリは非常に遅いです。

+0

おそらくクエリが遅いですか?最低限、クエリのパフォーマンスに関する質問には、すべての関連するテーブル(および好ましくはサンプルデータも)のCREATEステートメントと、EXPLAINの結果が必要です。 – Strawberry

+0

私はそれを更新しています。 – Tobia

答えて

2

は相関サブクエリとしてこれを実行してみてください:GROUP BYでインデックスを使用している場合

SELECT d.date, 
     (SELECT COUNT(l.id) 
     FROM log l 
     WHERE l.timest >= d.date AND l.timest < d.date + INTERVAL 1 DAY 
     ) as cnt 
FROM dates d; 

MySQLは非常に良いではありません。サブクエリを使用すると、パフォーマンスが大幅に向上することがあります。テーブルに正しいインデックスがあります。

+0

私はそれを試してみますが、パフォーマンスの大幅な向上はありません... – Tobia

+0

仕事中のテスト(MySQL 5.6.26):違いはありません。自宅でテストする(MariaDB 10.0.19):大きな違い。多分MySQL 5.7はMariaDB 10と同じくらい良いです。 –

+0

私はmysql 5.6.26でそれをテストしたことを確認します – Tobia

0

索引および相関サブクエリが機能しない場合は、日付表を更新してサマリー・カウント列を追加することをお薦めします。次に、ログ表に挿入すると、該当する日付の日付表のカウンターに1が追加されます。そのようなレコードがまだ存在しない場合は、それを追加し、新しいレコードであるためそのカウントを1に設定します。

次に、日付範囲に基づいて日付表からsum()を選択し、詳細を確認しないでください。検討のために所定の日付を選択すると、基礎となるデータを照会することができます。

0

これを回してください。日付範囲を制限したい場合は、中WHERE句を追加

SELECT date, 
     IFNULL(log.ct, 0) AS ct 
    FROM 
     (SELECT DATE(timest) AS date, 
       COUNT(*) AS ct 
      FROM test_log 
      GROUP BY date 
    ) AS log 
    RIGHT JOIN test_dates AS d USING(date); 

を両方:最初の欠落日(外側のクエリ)を記入し、その後、(以下、サブクエリを参照)は、第2のテーブルの上に効率的GROUP BYを行いますサブクエリと外部クエリ。