• 1
  • 2
  • 3
  • 4
  • 5
mysql数据库问题 首 页  »  帮助中心  »  数据库  »  mysql数据库问题
关于MySQL数据库查询优化的分析
发布日期:2015-11-28 15:11:29

  关于MySQL数据库查询优化的分析

  在优化查询中,数据库应用(比如说,MySQL)也就意味着对工具的操作与使用。使用索引、使用EXPLAIN分析查询以及调整MySQL的内部配置可达到优化查询的目的。

  #1: 使用索引

  MySQL允许对数据库表进行索引,这样就能迅速查找记录,而不用一开始就扫描整个表,这样就能显著地加快查询速度。每个表最多可以做到16个索引,除此之外,MySQL还支持多列索引及全文检索。

  给表添加一个索引非常的简单,只需调用一个CREATE INDEX命令并为索引指定它的域就可以了。列表A给出了一个例子:

  列表 A

  mysql> CREATE INDEX idx_username ON users(username);

  Query OK, 1 row affected (0.15 sec)

  Records: 1 Duplicates: 0 Warnings: 0

  这里,对users表的username域做索引,来确保在WHERE或者HAVING子句中引用这一域的SELECT查询语句运行速度比没有添加索引的时候要快。通过SHOW INDEX命令可以查看索引已被创建(列表B)。

  列表 B

  mysql> SHOW INDEX FROM users;

  --------------+-------------+-----------+-------------+----------+--------+------+------------+---------+

  | Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment |

  --------------+-------------+-----------+-------------+----------+--------+------+------------+---------+

  | users | 1 | idx_username | 1 | username | A | NULL | NULL | NULL | YES | BTREE | |

  --------------+-------------+-----------+-------------+----------+--------+------+------------+---------+

  1 row in set (0.00 sec)

  需要留意的是:索引就像一把双刃剑。对表的每一域做索引通常没有必要,且很可能会造成运行速度减慢,因为向表中插入或修改数据时,MySQL不得不每次都为这些额外的工作重新建立索引。另一方面,避免对表的每一域做索引同样不是一个特别好的主意,因为在提高插入记录的速度时,造成查询操作的速度减慢。这就需要找到一个平衡点,比如在设计索引系统时,考虑表的主要功能(数据修复及编辑)就是一种非常明智的选择。

  #2: 优化查询性能

  在分析查询性能时,考虑EXPLAIN关键字同样很管用。EXPLAIN关键字一般放在SELECT查询语句的前面,用于描述MySQL怎样执行查询操作、以及MySQL成功返回结果集需要执行的行数。下面就用一个简单例子来说明(列表C)这一过程:

  列表 C

  mysql> EXPLAIN SELECT city.name, city.district FROM city, country WHERE city.countrycode = country.code AND country.code = 'IND';

  +----+-------------+---------+-------+---------------+---------+---------+-------+------+-------------+

  | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |

  +----+-------------+---------+-------+---------------+---------+---------+-------+------+-------------+

  | 1 | SIMPLE | country | const | PRIMARY | PRIMARY | 3 | const | 1 | Using index |

  | 1 | SIMPLE | city | ALL | NULL | NULL | NULL | NULL | 4079 | Using where |

  +----+-------------+---------+-------+---------------+---------+---------+-------+------+-------------+

  2 rows in set (0.00 sec)这里查询是基于两个表连接。EXPLAIN关键字描述了MySQL是怎样处理连接这两个表。必须清楚的是,当前设计要求MySQL处理的是country表中的一条记录以及city表中的整个4019条记录。这就意味着,还可以使用其他的优化技巧改进其查询方法。比如说,给city表添加如下索引(列表D):

  列表 D

  mysql> CREATE INDEX idx_ccode ON city(countrycode);

  Query OK, 4079 rows affected (0.15 sec)

  Records: 4079 Duplicates: 0 Warnings: 0

  现在,当我们重新使用EXPLAIN关键字进行查询时,我们可以看到一个显著的改进(列表E):

  列表 E

  mysql> EXPLAIN SELECT city.name, city.district FROM city, country WHERE city.countrycode = country.code AND country.code = 'IND';

  +----+-------------+---------+-------+---------------+-----------+---------+-------+------+-------------+

  | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |

  +----+-------------+---------+-------+---------------+-----------+---------+-------+------+-------------+

  | 1 | SIMPLE | country | const | PRIMARY | PRIMARY | 3 | const | 1 | Using index |

  | 1 | SIMPLE | city | ref | idx_ccode | idx_ccode | 3 | const | 333 | Using where |

  +----+-------------+---------+-------+---------------+-----------+---------+-------+------+-------------+

  2 rows in set (0.01 sec)

  在这个例子中,MySQL现在只需要扫描city表中的333条记录就可产生一个结果集,它的扫描记录数几乎减少了90%!自然,数据库资源的查询速度更快,效率更高。

  #3: 调整内部变量

  MySQL是如此的开放,所以能够轻松地进一步调整其缺省设置以获得更优的性能及稳定性。需要优化的一些关键变量如下所述:

  (1)、read_buffer_size

   改变表长(read_buffer_size)  当一个查询不断地扫描某一个表,MySQL会为它分配一段内存缓冲区。read_buffer_size变量控制这一缓冲区的大小。如果你认为连续扫描进行得太慢,可以通过增加该变量值以及内存缓冲区大小的方法提高其性能。

  (2)、key_buffer

    改变索引缓冲区长度(key_buffer)  一般来说,这个变量控制缓冲区的长度在处理索引表(读/写操作)时使用。MySQL使用手册指出该变量能够不断增加以确保索引表的最佳性能,并推荐使用与系统内存25%的大小作为该变量的值。这是MySQL十分重要的配置变量之一,如果你对优化和提高系统性能有兴趣,可以从改变key_buffer_size变量的值开始。

  (3)、long_query_time

     对缓长查询设定一个时间限制(long_query_time)  MySQL带有“慢查询日志”,它能够自动地记录所有的在一个特定的时间范围内尚未结束的查询。这个日志对于跟踪那些低效率或者行为不端的查询以及寻找优化对象都非常有用。long_query_time变量控制这一最大时间限定,以秒为单位。

  (4)、table_cache

    设定打开表的数目的最大值(table_cache)  该变量控制MySQL在任何时候打开表的最大数目,由此能控制服务器响应输入请求的能力。它跟max_connections变量密切相关,增加table_cache值可使MySQL打开更多的表,就如增加max_connections值可增加连接数一样。当收到大量不同数据库及表的请求时,可以考虑改变这一值的大小。

  如果问题还未能解决,请联系售后技术支持。