mysql严重查询速度的问题一则
2011-07-11 21:03
211 查看
之前用mysql一直也没觉得有特别慢的感觉,最近发现新开发的系统有个页面打开速度非常慢,有时候1分钟都打不开。查了一下系统,定位到是一条sql语句执行慢造成的。该sql如下:
粗略看一下,真没觉得有非常严重的问题,只是本来该用内连接的写成了IN。查看执行计划结果如下:
+----+--------------------+------------------+------+-------------------------------------------+---------------------------+---------+------------+--------+----------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+--------------------+------------------+------+-------------------------------------------+---------------------------+---------+------------+--------+----------------------------------------------+
| 1 | PRIMARY | document | ALL | NULL | NULL | NULL | NULL | 117287 | Using where; Using temporary; Using filesort |
| 2 | DEPENDENT SUBQUERY | subject_document | ref | uk_subject_id_document_id,idx_document_id | uk_subject_id_document_id | 10 | const,func | 1 | Using where; Using index |
+----+--------------------+------------------+------+-------------------------------------------+---------------------------+---------+------------+--------+----------------------------------------------+
2 rows in set (0.41 sec)
嵌套的那个查询是用了索引的,但是外层没有用上索引,所以导致查询速度严重下降。
对比一下改成内连接后的执行计划:
+----+-------------+-------+--------+-------------------------------------------+---------------------------+---------+----------------------+------+-----------------------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+--------+-------------------------------------------+---------------------------+---------+----------------------+------+-----------------------------------------------------------+
| 1 | SIMPLE | sd | ref | uk_subject_id_document_id,idx_document_id | uk_subject_id_document_id | 5 | const | 455 | Using where; Using index; Using temporary; Using filesort |
| 1 | SIMPLE | d | eq_ref | PRIMARY | PRIMARY | 4 | pscms.sd.document_id | 1 | |
+----+-------------+-------+--------+-------------------------------------------+---------------------------+---------+----------------------+------+-----------------------------------------------------------+
2 rows in set (0.05 sec)
这就可以用上索引,所以查询速度非常快。
由于这个程序是从一个oracle数据库上代码移植过来的,所以特别去看了一下oracle的执行速度。结果在oracle上执行速度非常快,忘记看执行计划了,但显然是利用上索引。看来oracle的优化器做的要强大许多。
最后查看了一下自己的历史代码,里面还是有一些地方用到了IN。上面那个嵌套查询里面的子查询结果就算为空,居然也要执行很久。那如果直接写成 IN (1)呢?结果是速度又变得很快了,这要再不快,IN条件真一无是处了。查看了一下这个的执行计划:
+----+-------------+----------+-------+---------------+---------+---------+------+------+----------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+----------+-------+---------------+---------+---------+------+------+----------------------------------------------+
| 1 | SIMPLE | document | range | PRIMARY | PRIMARY | 4 | NULL | 2 | Using where; Using temporary; Using filesort |
+----+-------------+----------+-------+---------------+---------+---------+------+------+----------------------------------------------+
1 row in set (0.00 sec)
这里又用上了索引,因此速度又变快了。
总结一下,数据库的查询速度和索引有很大关系,正确利用索引可以有效的加快查询速度,另外还要多用执行计划去分析。
SELECT COUNT(1) AS value , document.sourceType AS lable FROM document WHERE document.id IN (SELECT document_id FROM subject_document WHERE subject_id = 345 ) GROUP BY document.sourceType
粗略看一下,真没觉得有非常严重的问题,只是本来该用内连接的写成了IN。查看执行计划结果如下:
+----+--------------------+------------------+------+-------------------------------------------+---------------------------+---------+------------+--------+----------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+--------------------+------------------+------+-------------------------------------------+---------------------------+---------+------------+--------+----------------------------------------------+
| 1 | PRIMARY | document | ALL | NULL | NULL | NULL | NULL | 117287 | Using where; Using temporary; Using filesort |
| 2 | DEPENDENT SUBQUERY | subject_document | ref | uk_subject_id_document_id,idx_document_id | uk_subject_id_document_id | 10 | const,func | 1 | Using where; Using index |
+----+--------------------+------------------+------+-------------------------------------------+---------------------------+---------+------------+--------+----------------------------------------------+
2 rows in set (0.41 sec)
嵌套的那个查询是用了索引的,但是外层没有用上索引,所以导致查询速度严重下降。
对比一下改成内连接后的执行计划:
+----+-------------+-------+--------+-------------------------------------------+---------------------------+---------+----------------------+------+-----------------------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+--------+-------------------------------------------+---------------------------+---------+----------------------+------+-----------------------------------------------------------+
| 1 | SIMPLE | sd | ref | uk_subject_id_document_id,idx_document_id | uk_subject_id_document_id | 5 | const | 455 | Using where; Using index; Using temporary; Using filesort |
| 1 | SIMPLE | d | eq_ref | PRIMARY | PRIMARY | 4 | pscms.sd.document_id | 1 | |
+----+-------------+-------+--------+-------------------------------------------+---------------------------+---------+----------------------+------+-----------------------------------------------------------+
2 rows in set (0.05 sec)
这就可以用上索引,所以查询速度非常快。
由于这个程序是从一个oracle数据库上代码移植过来的,所以特别去看了一下oracle的执行速度。结果在oracle上执行速度非常快,忘记看执行计划了,但显然是利用上索引。看来oracle的优化器做的要强大许多。
最后查看了一下自己的历史代码,里面还是有一些地方用到了IN。上面那个嵌套查询里面的子查询结果就算为空,居然也要执行很久。那如果直接写成 IN (1)呢?结果是速度又变得很快了,这要再不快,IN条件真一无是处了。查看了一下这个的执行计划:
+----+-------------+----------+-------+---------------+---------+---------+------+------+----------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+----------+-------+---------------+---------+---------+------+------+----------------------------------------------+
| 1 | SIMPLE | document | range | PRIMARY | PRIMARY | 4 | NULL | 2 | Using where; Using temporary; Using filesort |
+----+-------------+----------+-------+---------------+---------+---------+------+------+----------------------------------------------+
1 row in set (0.00 sec)
这里又用上了索引,因此速度又变快了。
总结一下,数据库的查询速度和索引有很大关系,正确利用索引可以有效的加快查询速度,另外还要多用执行计划去分析。
相关文章推荐
- mysql严重查询速度的问题一则
- 对于Mysql大量数据查询速度慢的问题
- mysql查询均有索引但速度慢问题排查
- 关于mysql处理百万级以上的数据时如何提高其查询速度的方法
- MySQL加速查询速度的独门武器:查询缓存
- MYSQL索引问题:索引在查询中如何使用?(转载)
- mysql问题: alter导致速度慢
- MySQL 中文显示乱码以及中文查询条件返回0条结果的问题解决
- MySQL查询不区分大小写问题
- MySQL查询全部数据集结果不一致问题解决方案
- MySQL字符集中文乱码终极解决方案和mysql查询中文问题解决方法[转贴]
- 关于mysql处理百万级以上的数据时如何提高其查询速度的方法
- [MySQL] 实现树形的遍历(关于多级菜单栏以及多级上下部门的查询问题)
- 如何提高MySQL查询速度
- 关于Oracle、Mysql、SQLServer中指定查询结果中返回的行数问题!
- 解决MySQL Sending data导致查询很慢问题的方法与思路
- Navicat for MySQL 新建查询时,报can't create file ...系统找不到指定的文件夹出现问题
- MySQL-----MySQL中max函数查询最大值问题
- 解决模糊查询速度慢问题(ORACLE)
- mysql查询不区分大小写问题分析和解决