首页 > 代码库 > MySQL之查询优化方式(笔记)

MySQL之查询优化方式(笔记)

1.COUNT()

  对COUNT的优化可以通过下面的SQL实现

  

mysql> select count(gnp<10000 or null) as  ‘<<<<‘,count(gnp>=10000 or null) as ‘>>>>‘ from country;+------+------+| <<<< | >>>> |+------+------+|  152 |   87 |+------+------+1 row in set (0.00 sec)

count(*)与count(cloumn)返回的值可能不一样,因为如果存在空的情况,count(*)也会计算在内

2.SUM()

对SUM()的优化需要通过建立索引实现

  

mysql> desc city;+-------------+----------+------+-----+---------+----------------+| Field       | Type     | Null | Key | Default | Extra          |+-------------+----------+------+-----+---------+----------------+| ID          | int(11)  | NO   | PRI | NULL    | auto_increment || Name        | char(35) | NO   | MUL |         |                || CountryCode | char(3)  | NO   |     |         |                || District    | char(20) | NO   |     |         |                || Population  | int(11)  | NO   |     | 0       |                |+-------------+----------+------+-----+---------+----------------+5 rows in set (0.03 sec)mysql> create index popu_index on city(population);Query OK, 4079 rows affected (0.05 sec)Records: 4079  Duplicates: 0  Warnings: 0mysql> explain select SUM(population) as  sum from city;+----+-------------+-------+-------+---------------+------------+---------+------+------+-------------+| id | select_type | table | type  | possible_keys | key        | key_len | ref  | rows | Extra       |+----+-------------+-------+-------+---------------+------------+---------+------+------+-------------+|  1 | SIMPLE      | city  | index | NULL          | popu_index | 4       | NULL | 4079 | Using index |+----+-------------+-------+-------+---------------+------------+---------+------+------+-------------+1 row in set (0.00 sec)mysql> select SUM(population) as  sum from city;+------------+| sum        |+------------+| 1429559884 |+------------+1 row in set (0.00 sec)

 3.子查询的优化

  对于子查询的优化可以通过on实现

 

mysql> desc city;+-------------+----------+------+-----+---------+----------------+| Field       | Type     | Null | Key | Default | Extra          |+-------------+----------+------+-----+---------+----------------+| ID          | int(11)  | NO   | PRI | NULL    | auto_increment || Name        | char(35) | NO   | MUL |         |                || CountryCode | char(3)  | NO   |     |         |                || District    | char(20) | NO   |     |         |                || Population  | int(11)  | NO   | MUL | 0       |                |+-------------+----------+------+-----+---------+----------------+5 rows in set (0.01 sec)mysql> desc country;;+----------------+---------------------------------------------------------------------------------------+------+-----+---------+--| Field          | Type                                                                                  | Null | Key | Default | E+----------------+---------------------------------------------------------------------------------------+------+-----+---------+--| Code           | char(3)                                                                               | NO   | PRI |         || Name           | char(52)                                                                              | NO   |     |         || Continent      | enum(‘Asia‘,‘Europe‘,‘North America‘,‘Africa‘,‘Oceania‘,‘Antarctica‘,‘South America‘) | NO   |     | Asia    || Region         | char(26)                                                                              | NO   |     |         || SurfaceArea    | float(10,2)                                                                           | NO   |     | 0.00    || IndepYear      | smallint(6)                                                                           | YES  |     | NULL    || Population     | int(11)                                                                               | NO   |     | 0       || LifeExpectancy | float(3,1)                                                                            | YES  |     | NULL    || GNP            | float(10,2)                                                                           | YES  |     | NULL    || GNPOld         | float(10,2)                                                                           | YES  |     | NULL    || LocalName      | char(45)                                                                              | NO   |     |         || GovernmentForm | char(45)                                                                              | NO   |     |         || HeadOfState    | char(60)                                                                              | YES  |     | NULL    || Capital        | int(11)                                                                               | YES  |     | NULL    || Code2          | char(2)                                                                               | NO   |     |         |+----------------+---------------------------------------------------------------------------------------+------+-----+---------+--15 rows in set (0.01 sec)ERROR:No query specifiedmysql> explain select t.* from city t where t.countrycode in( select code from country);+----+-------------+---------+--------+---------------+---------+---------+---------------------+------+-------------+| id | select_type | table   | type   | possible_keys | key     | key_len | ref                 | rows | Extra       |+----+-------------+---------+--------+---------------+---------+---------+---------------------+------+-------------+|  1 | SIMPLE      | t       | ALL    | NULL          | NULL    | NULL    | NULL                | 4079 | NULL        ||  1 | SIMPLE      | country | eq_ref | PRIMARY       | PRIMARY | 3       | world.t.CountryCode |    1 | Using index |+----+-------------+---------+--------+---------------+---------+---------+---------------------+------+-------------+2 rows in set (0.04 sec)mysql> explain select t.* from city t join country t1 on t.countrycode = t1.code;+----+-------------+-------+--------+---------------+---------+---------+---------------------+------+-------------+| id | select_type | table | type   | possible_keys | key     | key_len | ref                 | rows | Extra       |+----+-------------+-------+--------+---------------+---------+---------+---------------------+------+-------------+|  1 | SIMPLE      | t     | ALL    | NULL          | NULL    | NULL    | NULL                | 4079 | NULL        ||  1 | SIMPLE      | t1    | eq_ref | PRIMARY       | PRIMARY | 3       | world.t.CountryCode |    1 | Using index |+----+-------------+-------+--------+---------------+---------+---------+---------------------+------+-------------+2 rows in set (0.00 sec)

  这样的优化可能返回重复的行,去重需要使用关键字distinct

4.Group  by优化

正常执行情况下如下

  

mysql> explain select t.* from city t join country t1 on t.countrycode = t1.code group by t.id;+----+-------------+-------+--------+---------------+---------+---------+---------------------+------+---------------------------------+| id | select_type | table | type   | possible_keys | key     | key_len | ref                 | rows | Extra                           |+----+-------------+-------+--------+---------------+---------+---------+---------------------+------+---------------------------------+|  1 | SIMPLE      | t     | ALL    | NULL          | NULL    | NULL    | NULL                | 4079 | Using temporary; Using filesort ||  1 | SIMPLE      | t1    | eq_ref | PRIMARY       | PRIMARY | 3       | world.t.CountryCode |    1 | Using index                     |+----+-------------+-------+--------+---------------+---------+---------+---------------------+------+---------------------------------+2 rows in set (0.02 sec)

  可以看到了使用临时表还有文件排序的方式来实现,那么我们应该怎么减少IO已经对资源的消耗呢,通过下面方式可以看出

mysql> explain select t.* from city t join (select code from country) t1 on t.countrycode = t1.code;+----+-------------+------------+-------+---------------+-------------+---------+---------------------+------+-------------+| id | select_type | table      | type  | possible_keys | key         | key_len | ref                 | rows | Extra       |+----+-------------+------------+-------+---------------+-------------+---------+---------------------+------+-------------+|  1 | PRIMARY     | t          | ALL   | NULL          | NULL        | NULL    | NULL                | 4079 | NULL        ||  1 | PRIMARY     | <derived2> | ref   | <auto_key0>   | <auto_key0> | 3       | world.t.CountryCode |   10 | Using index ||  2 | DERIVED     | country    | index | NULL          | PRIMARY     | 3       | NULL                |  239 | Using index |+----+-------------+------------+-------+---------------+-------------+---------+---------------------+------+-------------+3 rows in set (0.00 sec)

  这样就可以避免了文件排序还有使用该临时表的情况。

5.limit操作方式的优化

  使用之前:

mysql> explain select * from city order by name limit  100,10;+----+-------------+-------+------+---------------+------+---------+------+------+----------------+| id | select_type | table | type | possible_keys | key  | key_len | ref  | rows | Extra          |+----+-------------+-------+------+---------------+------+---------+------+------+----------------+|  1 | SIMPLE      | city  | ALL  | NULL          | NULL | NULL    | NULL | 4079 | Using filesort |+----+-------------+-------+------+---------------+------+---------+------+------+----------------+1 row in set (0.00 sec)

  可以看到使用了文件排序,这样会造成性能上的低下。

  优化方式:可以通过主键或者是含有索引的列进行order by  操作;

  

mysql> create index name_index  on city(name);mysql> explain select name from city order by name limit  100,10;+----+-------------+-------+-------+---------------+------------+---------+------+------+-------------+| id | select_type | table | type  | possible_keys | key        | key_len | ref  | rows | Extra       |+----+-------------+-------+-------+---------------+------------+---------+------+------+-------------+|  1 | SIMPLE      | city  | index | NULL          | name_index | 35      | NULL |  110 | Using index |+----+-------------+-------+-------+---------------+------------+---------+------+------+-------------+1 row in set (0.00 sec)

  可以发现只扫描了35行而且使用了索引但是效率增加了很多。

MySQL之查询优化方式(笔记)