我试图解决以下问题大约一个小时,但仍然没有解决任何问题。
好的,我有一张桌子(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秒才能运行。
哪个索引会很聪明?我认为索引日期会给我“不好的”基数,因此MySQL不会使用它。http也是一个不好的选择,因为只有大约20个不同的可能值。
感谢您的帮助!
更新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 | |
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
和EXPLAIN
+----+--------------------+-------+-------+---------------+----------+---------+------+-------+-----------------------------------------------------------+
| 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)
您还可以添加mysql版本吗,表的引擎是什么?(的myisam或innodb的)
—
ypercubeᵀᴹ
MyISAM和5.1.73-现在发布所有详细信息。
—
罗宾·海勒2014年
恐怕可能与该
—
ypercubeᵀᴹ
http
列可为空有关。如果有时间,我明天会调查。
恐怕可能与http列可为空有关。如果有时间,我明天会调查。您可以通过以下方式进行测试:创建一个相同的表(除外
—
。–ypercubeᵀᴹ2014年
http NOT NULL
),然后将所有数据复制到该表中(当然,除了带有http NULL的行之外)
将其更改为NOT NULL(这完全有可能,创建表时我不太在意)将查询(我的查询)的性能提高到大约1s-1.6s。感谢您到目前为止的努力。
—
罗宾·海勒