次の問題を約1時間解決しようとしましたが、それでも解決しませんでした。
さて、私はテーブルを持っています(MyISAM):
+---------+-------------+------+-----+-------------------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------+-------------+------+-----+-------------------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| http | smallint(3) | YES | MUL | 200 | |
| elapsed | float(6,3) | NO | | NULL | |
| cached | tinyint(1) | YES | | NULL | |
| ip | int(11) | NO | | NULL | |
| date | timestamp | NO | MUL | CURRENT_TIMESTAMP | |
+---------+-------------+------+-----+-------------------+----------------+
インデックスを気にしないでください。私は解決策を見つけることを試みて遊んでいます。さて、これが私のクエリです。
SELECT http,
COUNT( http ) AS count
FROM reqs
WHERE DATE(date) >= cast(date_sub(date(NOW()),interval 24 hour) as datetime)
GROUP BY http
ORDER BY count;
テーブルは着信Webリクエストに関する情報を格納しているため、かなり大きなデータベースです。
+-----------+
| count(id) |
+-----------+
| 782412 |
+-----------+
id列が唯一の一意の識別子になるため、主キーを設定するより良い方法はないことに注意してください。上記のクエリの実行には、約0.6〜1.6秒かかります。
どのインデックスが賢いでしょうか?インデックス付けdateによって「悪い」カーディナリティが得られるため、MySQLはそれを使用しないと考えました。 httpも、20種類の可能な値しかないため、不適切な選択です。
助けてくれてありがとう!
pdate 1 ypercubeが提案したように、(http、date)にインデックスを追加しました:
mysql> CREATE INDEX httpDate ON reqs (http, date);
と彼のクエリを使用しましたが、同じように悪いパフォーマンスをしました。追加されたインデックス:
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment |
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
| reqs | 0 | PRIMARY | 1 | id | A | 798869 | NULL | NULL | | BTREE | |
| reqs | 1 | httpDate | 1 | http | A | 19 | NULL | NULL | YES | BTREE | |
| reqs | 1 | httpDate | 2 | date | A | 99858 | NULL | NULL | | BTREE | |
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
および[〜#〜]説明[〜#〜]
+----+--------------------+-------+-------+---------------+----------+---------+------+-------+-----------------------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+--------------------+-------+-------+---------------+----------+---------+------+-------+-----------------------------------------------------------+
| 1 | PRIMARY | r | range | NULL | httpDate | 3 | NULL | 20 | Using index for group-by; Using temporary; Using filesort |
| 2 | DEPENDENT SUBQUERY | ri | ref | httpDate | httpDate | 3 | func | 41768 | Using where; Using index |
+----+--------------------+-------+-------+---------------+----------+---------+------+-------+-----------------------------------------------------------+
MySQLサーバーのバージョン:
mysql> SHOW VARIABLES LIKE "%version%";
+-------------------------+---------------------+
| Variable_name | Value |
+-------------------------+---------------------+
| protocol_version | 10 |
| version | 5.1.73 |
| version_comment | Source distribution |
| version_compile_machine | x86_64 |
| version_compile_os | redhat-linux-gnu |
+-------------------------+---------------------+
5 rows in set (0.00 sec)
3つの提案があります
次のようにクエリを書き直す必要があります
SELECT http,
COUNT( http ) AS count
FROM reqs
WHERE date >= ( DATE(NOW() - INTERVAL 1 DAY) + INTERVAL 0 SECOND )
GROUP BY http
ORDER BY count;
または
SELECT * FROM
(
SELECT http,
COUNT( http ) AS count
FROM reqs
WHERE date >= ( DATE(NOW() - INTERVAL 1 DAY) + INTERVAL 0 SECOND )
GROUP BY http
) A ORDER BY count;
WHEREには、等号の両側に関数があってはなりません。等号の左側に日付があると、クエリオプティマイザーがそれに対してインデックスを使用しやすくなります。
別のインデックスも提案します
ALTER TABLE reqs ADD INDEX date_http_ndx (date,http); -- not (http,date)
date
エントリはすべてインデックス内で連続しているため、この列の順序をお勧めします。次に、クエリはhttp
のギャップをスキップせずにhttp
値を収集するだけです。
MyISAMはインデックスキャッシングのみを使用します。クエリは.MYD
ファイルに触れないようにする必要があるため、少し大きいMyISAMキーバッファーを使用する必要があります。
256Mに設定するには
SET @newsize = 1024 * 1024 * 256;
SET GLOBAL key_buffer_size = @newsize;
次に、my.cnf
に設定します
[mysqld]
key_buffer_size = 256M
MySQLの再起動は不要