2011-06-24 5 views
1

current_vacature_responseに88kレコードが含まれており、daily_vacature_responseに10kレコードが含まれている場合、次のクエリの実行に約30秒かかります。 EXPLAINの使用私は、current_vacature_responseテーブルから使用されたインデックスがないと結論付けました。私は基本的なインデックスをいくつか追加しましたが、どれも使用されていないようです。このクエリを高速化するためには、どのようなインデックスを設定する必要がありますか?このMYSQL JOIN/GROUP BY/HAVINGクエリを高速化するために、どのインデックスを追加する必要がありますか?

問合せ:

SELECT c.`stats_date` as `stats_date` 
    FROM `current_vacature_response` c 
    LEFT JOIN `daily_vacature_response` d ON (c.`stats_date` = d.`stats_date`) 
    GROUP BY c.`stats_date`, d.`stats_date` 
    HAVING max(d.`last_stats_datetime`) IS NULL 
     OR MAX(d.`last_stats_datetime`) < MAX(c.`created_datetime`); 

current_vacature_responseテーブル定義:

CREATE TABLE `current_vacature_response` (
    `id` int(10) unsigned NOT NULL AUTO_INCREMENT, 
    `created_datetime` datetime NOT NULL, 
    `site_id` tinyint(1) unsigned NOT NULL, 
    `stats_date` date NOT NULL, 
    `type` enum('typ1', 'type2') NOT NULL, 
    `vacature` int(10) unsigned NOT NULL, 
    PRIMARY KEY (`id`), 
    KEY `current_vacature_created_datetime` (`created_datetime`), 
    KEY `current_vacature_response_vacature` (`vacature`), 
    KEY `current_vacature_response_type` (`type`), 
    KEY `current_vacature_stats_date` (`stats_date`) 
) ENGINE=MyISAM AUTO_INCREMENT=88210 DEFAULT CHARSET=utf8; 

daily_vacature_responseテーブル定義:

CREATE TABLE `daily_vacature_response` (
    `id` int(10) unsigned NOT NULL AUTO_INCREMENT, 
    `contact` int(10) unsigned NOT NULL DEFAULT '0', 
    `site_id` tinyint(1) unsigned NOT NULL, 
    `spotlight_result` int(10) unsigned NOT NULL DEFAULT '0', 
    `stats_date` date NOT NULL, 
    `last_stats_datetime` datetime NOT NULL, 
    `vacature` int(10) unsigned NOT NULL, 
    `created_datetime` datetime NOT NULL, 
    PRIMARY KEY (`id`), 
    UNIQUE KEY `daily_vacature_response_key` (`site_id`,`vacature`,`stats_date`), 
    KEY `daily_vacature_response_last_stats_datetime` (`last_stats_datetime`), 
    KEY `daily_vacature_response_stats_date` (`stats_date`) 
) ENGINE=MyISAM AUTO_INCREMENT=9802 DEFAULT CHARSET=utf8; 

は説明出力:

*************************** 1. row *************************** 
      id: 1 
    select_type: SIMPLE 
     table: c 
     type: ALL 
possible_keys: NULL 
      key: NULL 
     key_len: NULL 
      ref: NULL 
     rows: 88209 
     Extra: Using temporary; Using filesort 
*************************** 2. row *************************** 
      id: 1 
    select_type: SIMPLE 
     table: d 
     type: ref 
possible_keys: daily_vacature_response_stats_date 
      key: daily_vacature_response_stats_date 
     key_len: 3 
      ref: reporting_development.c.stats_date 
     rows: 99 
     Extra: 
+2

あなたは他のすべての操作の後に実行される句を、HAVINGにのみフィルタリングしているので、それはあまりにもです索引を使用するのが遅れます。フィルタリングが早い段階(where句または結合条件)で実行されるようにクエリを書き換えることが最善の方法です。そうしないと、MySQLは常にcurrent_vacature_responseテーブル全体をスキャンする必要があります。だから唯一の解決策は、クエリを書き換えることですが、それを確実に行うために、stats_date、created_datetime、last_stats_datetimeについて説明してください。あなたはまた、いくつかの入力例と期待される出力を提供できますか? –

+0

TNX、私はそれをはるかに高速クエリ(4MS)を書き換えました:c.'stats_date' BY current_cv_response'のC \t GROUP 'FROM c.'stats_date' \tを選択 \t MAX(c.'created_datetime'を)持っていません \t IN(d.'stats_date' BY daily_cv_response' D \t \t d.'stats_date' = c.'stats_date' \t \t GROUP 'FROM MAX(d.'last_stats_datetime') \t \tを選択します)。 –

答えて

1

daily_vacature_response(stats_date, last_stats_datetime)でインデックスを検索してください。

私はそれが大きな違いになるとは疑いがありますが、それが最も有望な候補です。

また、(MySQLでは動作しますが、試してみる価値はないかもしれません)クエリを少し書き換えてみてください。

GROUP BY c.`stats_date`, c.`created_datetime`, d.`stats_date` 
HAVING max(d.`last_stats_datetime`) IS NULL 
    OR max(d.`last_stats_datetime`) < c.`created_datetime`; 
関連する問題