毎日リクエストを行った個別の IP アドレスを示す次のクエリがあります。
SELECT COUNT(DISTINCT ip_address) as ip_address, DATE(exec_datetime) as day
FROM requests
GROUP BY MONTH(exec_datetime), DAY(exec_datetime);
の出力EXPLAIN
は次のとおりです
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE requests ALL NULL NULL NULL NULL 472043 Using filesort
インデックスを作成したとき、クエリが完了するまでに時間がかかったので、インデックスをカバーすることについて明確に理解していません。
ALTER TABLE requests ADD INDEX unique_ip_per_time(ip_address, exec_datetime);
これがの出力ですEXPLAIN
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE requests index NULL unique_ip_per_time 268 NULL 472043 Using index; Using filesort
インデックスを作成するか書き直して、このクエリを最適化するにはどうすればよいでしょうか?
編集
実行時間は、両方のステートメント (カバー インデックスの有無) で約 15 秒です。このテーブルの唯一の他のキーはUNIQUE
サロゲートとINDEX
オンですip_address
show indexes from requests
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
requests 0 PRIMARY 1 request_id A 386577 NULL NULL BTREE
requests 1 ip_address 1 ip_address A 193288 NULL NULL YES BTREE
requests 1 unique_ip_per_time 1 ip_address A 163 NULL NULL YES BTREE
requests 1 unique_ip_per_time 2 exec_datetime A 163 NULL NULL YES BTREE
編集2
私はEisbergの指示に従いましたが、このクエリには約1.1秒かかります...
EXPLAIN SELECT
A.request_day,
(
SELECT COUNT(DISTINCT B.ip_address)
FROM requests B
WHERE B.exec_date = A.request_day
) as num_ip_addr
FROM request_days A
ORDER BY A.request_day ASC;
これは、約 0.9 秒かかるこのクエリよりもわずかに遅いです
SELECT COUNT(DISTINCT ip_address) as ip_address, exec_date
FROM requests
GROUP BY exec_date;
日付を含む追加のテーブルを作成する必要はないと思います。ステートメントの一部に適用できる最適化はありますかDISTINCT ip_address
(ボトルネックのようです)?