首先声明,下面的分析十分以及相当浅薄.
在mysql中:
v4.0, 4.1, 5.0, v5.1 到 5.1.20(包括):不支持毫秒级别的慢查询分析(支持精度为1-10秒);
5.1.21+ :支持毫秒级别的慢查询分析;
6.0 到 6.0.3: 不支持毫秒级别的慢查询分析(支持精度为1-10秒);
6.0.4+:支持毫秒级别的慢查询分析;
总而言之,如果不支持毫秒级别的慢查询分析则 patch it to allow microsecond support
首先确认mysql的版本: 5.1.44-log
打开慢查询功能
#vim /etc/my.cnf
long_query_time=0.5
log-slow-queries= /usr/var/slowquery.log
超过0.5秒的查询基本是无法忍受的了.
下面来看一个比较慢的查询:
mysql> select temp_value from temperatures where temp_value > 15;
844827 rows in set (2.01 sec)
mysql> explain select temp_value from temperatures where temp_value > 15;
+----+-------------+--------------+------+---------------+------+---------+------+---------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+--------------+------+---------------+------+---------+------+---------+-------------+
| 1 | SIMPLE | temperatures | ALL | NULL | NULL | NULL | NULL | 1273287 | Using where |
+----+-------------+--------------+------+---------------+------+---------+------+---------+-------------+
1 row in set (0.00 sec)
这个语句很简单阿,怎么会这么慢呢?:
mysql> select count(*) from temperatures;
+----------+
| count(*) |
+----------+
| 1273062 |
+----------+
1 row in set (1.01 sec)
毫无怀疑是记录数太多了,超过了百万条.加个索引来看看:
mysql> create index idx_value on temperatures (temp_value);
mysql> alter table temperatures drop index idx_value; #这个是删除索引的一种方法.
mysql> show index from temperatures; #这个是查看索引的一种方法.
+--------------+------------+-----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment |
+--------------+------------+-----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
| temperatures | 0 | PRIMARY | 1 | id | A | 1273561 | NULL | NULL | | BTREE | |
| temperatures | 1 | idx_value | 1 | temp_value | A | 314 | NULL | NULL | YES | BTREE | |
+--------------+------------+-----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
然后再来看看查询速度:
mysql> select temp_value from temperatures where temp_value > 15;
844895 rows in set (0.86 sec)
mysql> explain select temp_value from temperatures where temp_value > 15;
+----+-------------+--------------+-------+---------------+-----------+---------+------+--------+--------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+--------------+-------+---------------+-----------+---------+------+--------+--------------------------+
| 1 | SIMPLE | temperatures | range | idx_value | idx_value | 4 | NULL | 636591 | Using where; Using index |
+----+-------------+--------------+-------+---------------+-----------+---------+------+--------+--------------------------+
1 row in set (0.00 sec)
可以看到使用了索引,查询时间降到了1秒内,但是说实话速度没有快多少,不解.
再看一个慢查询:
mysql> SELECT * FROM `temperatures` WHERE (device_id in (91,92,93,94,95,96,97,98,99) and created_at >= '2010-05-06 03:26:06');
70182 rows in set (1.61 sec)
mysql> explain SELECT * FROM `temperatures` WHERE (device_id in (91,92,93,94,95,96,97,98,99) and created_at >= '2010-05-06 03:26:06');
+----+-------------+--------------+------+---------------+------+---------+------+---------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+--------------+------+---------------+------+---------+------+---------+-------------+
| 1 | SIMPLE | temperatures | ALL | NULL | NULL | NULL | NULL | 1273561 | Using where |
+----+-------------+--------------+------+---------------+------+---------+------+---------+-------------+
该查询检查了所有的100万条数据,慢是理所当然的.
我们尝试加入索引:
mysql> create index idx_device_created_at on temperatures (device_id,created_at);
再来看看效果:
mysql> SELECT * FROM `temperatures` WHERE (device_id in (91,92,93,94,95,96,97,98,99) and created_at >= '2010-05-06 03:26:06');
70191 rows in set (1.67 sec)
mysql> explain SELECT * FROM `temperatures` WHERE (device_id in (91,92,93,94,95,96,97,98,99) and created_at >= '2010-05-06 03:26:06');
+----+-------------+--------------+-------+-----------------------+-----------------------+---------+------+-------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+--------------+-------+-----------------------+-----------------------+---------+------+-------+-------------+
| 1 | SIMPLE | temperatures | range | idx_device_created_at | idx_device_created_at | 14 | NULL | 89250 | Using where |
+----+-------------+--------------+-------+-----------------------+-----------------------+---------+------+-------+-------------+
就一个字:没有使用索引,崩溃阿!
比刚才还慢.
避免使用in 或者 or (or会导致扫表)
看下面一个查询:
mysql> SELECT * FROM `temperatures` WHERE (device_id = 182 and current = 1) LIMIT 1;
+---------+-----------+------------+---------------------+---------------------+---------+---------------------+
| id | device_id | temp_value | created_at | updated_at | current | time |
+---------+-----------+------------+---------------------+---------------------+---------+---------------------+
| 1423040 | 182 | 16.5 | 2010-05-18 09:10:03 | 2010-05-18 09:10:03 | 1 | 2010-05-18 09:10:03 |
+---------+-----------+------------+---------------------+---------------------+---------+---------------------+
1 row in set (0.25 sec)
mysql> explain SELECT * FROM `temperatures` WHERE (device_id = 182 and current = 1) LIMIT 1;
+----+-------------+--------------+------+---------------+------+---------+------+--------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+--------------+------+---------------+------+---------+------+--------+-------------+
| 1 | SIMPLE | temperatures | ALL | NULL | NULL | NULL | NULL | 423269 | Using where |
+----+-------------+--------------+------+---------------+------+---------+------+--------+-------------+
1 row in set (0.00 sec)
竟然检查了23269行,不慢才怪.
加上索引试试看:
mysql> create index idx_device_id_current on temperatures(device_id,current);
Query OK, 423051 rows affected (1 min 0.62 sec)
Records: 423051 Duplicates: 0 Warnings: 0
再看看查询速度:
mysql> SELECT * FROM `temperatures` WHERE (device_id = 182 and current = 1) LIMIT 1;
+---------+-----------+------------+---------------------+---------------------+---------+---------------------+
| id | device_id | temp_value | created_at | updated_at | current | time |
+---------+-----------+------------+---------------------+---------------------+---------+---------------------+
| 1423040 | 182 | 16.5 | 2010-05-18 09:10:03 | 2010-05-18 09:10:03 | 1 | 2010-05-18 09:10:03 |
+---------+-----------+------------+---------------------+---------------------+---------+---------------------+
1 row in set (0.00 sec)
mysql> explain SELECT * FROM `temperatures` WHERE (device_id = 182 and current = 1) LIMIT 1;
+----+-------------+--------------+------+-----------------------+-----------------------+---------+-------------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+--------------+------+-----------------------+-----------------------+---------+-------------+------+-------------+
| 1 | SIMPLE | temperatures | ref | idx_device_id_current | idx_device_id_current | 7 | const,const | 1 | Using where |
+----+-------------+--------------+------+-----------------------+-----------------------+---------+-------------+------+-------------+
1 row in set (0.00 sec)
可以看到只检查了一行,速度当然快了
Mysql慢查询分析
原创
©著作权归作者所有:来自51CTO博客作者weekface的原创作品,请联系作者获取转载授权,否则将追究法律责任
下一篇:Vsftpd虚拟用户设置
提问和评论都可以,用心的回复会被更多人看到
评论
发布评论
相关文章