我爱编程

MySQL查询优化

2017-07-31  本文已影响281人  maxwellyue

1、开启MySQL查询的缓存功能(Query Cache)

通过show variables like "%query_cache%"查看与查询缓存相关的参数:

mysql> show variables like "%query_cache%";
+------------------------------+---------+
| Variable_name                | Value   |
+------------------------------+---------+
| have_query_cache             | YES     |
| query_cache_limit            | 1048576 |
| query_cache_min_res_unit     | 1024    |
| query_cache_size             | 3145728 |
| query_cache_type             | OFF     |
| query_cache_wlock_invalidate | OFF     |
+------------------------------+---------+
6 rows in set (0.02 sec)

但Query Cache有如下规则,如果数据表被更改,那么和这个数据表相关的全部Cache全部都会无效,并删除。这里“数据表更改”包括: INSERT, UPDATE, DELETE, TRUNCATE, ALTER TABLE, DROP TABLE, or DROP DATABASE等。如果你的数据表更新频繁的话,那么Query Cache将会成为系统的负担。如果你的应用对数据库的更新很少,那么Query Cache将会作用显著。

参考:理解MySQL数据库查询缓存以及Query Cache,看上去很美


使用EXPLAIN 分析SELECT 查询

在任意的SELECT查询语句的前面加上EXPLAIN这个词,就可以分析MySQL在执行该语句时的具体信息:

# 示例1
mysql> explain select 1\G
*************************** 1. row ***************************
id           : 1
select_type  : SIMPLE
table        : NULL
type         : NULL
possible_keys: NULL
key          : NULL
key_len      : NULL
ref          : NULL
rows         : NULL
Extra        : No tables used
1 rows in set (0.05 sec)

# 示例2
mysql> explain select dept_name from hr_department d left join hr_person p on p.dept_id=d.dept_id;
+----+-------------+-------+------+---------------+------+---------+------+------+----------------------------------------------------+
| id | select_type | table | type | possible_keys | key  | key_len | ref  | rows | Extra                                              |
+----+-------------+-------+------+---------------+------+---------+------+------+----------------------------------------------------+
| 1  | SIMPLE      | d     | ALL  | NULL          | NULL | NULL    | NULL | 541  | NULL                                               |
| 1  | SIMPLE      | p     | ALL  | NULL          | NULL | NULL    | NULL | 561  | Using where; Using join buffer (Block Nested Loop) |
+----+-------------+-------+------+---------------+------+---------+------+------+----------------------------------------------------+
2 rows in set (0.05 sec)

# 示例3
mysql> explain select dept_name from hr_department union  select dept_name from hr_department_copy;
+----+--------------+--------------------+------+---------------+------+---------+------+------+-----------------+
| id | select_type  | table              | type | possible_keys | key  | key_len | ref  | rows | Extra           |
+----+--------------+--------------------+------+---------------+------+---------+------+------+-----------------+
| 1  | PRIMARY      | hr_department      | ALL  | NULL          | NULL | NULL    | NULL | 541  | NULL            |
| 2  | UNION        | hr_department_copy | ALL  | NULL          | NULL | NULL    | NULL | 540  | NULL            |
| NULL | UNION RESULT | <union1,2>         | ALL  | NULL          | NULL | NULL    | NULL | NULL | Using temporary |
+----+--------------+--------------------+------+---------------+------+---------+------+------+-----------------+
3 rows in set (0.08 sec)

EXPLAIN的结果行是以MySQL实际执行的查询部分的顺序出现的。

各参数含义:

参考:《高性能MySQL》


创建(正确)索引

索引并不一定就是给主键或是唯一的字段。如果在你的表中,有某个字段你总要会经常用来做搜索,那么,请为其建立索引吧。
一些注意点:
①在Join表的时候使用相当类型的例,并将其索引

SELECT company_name FROM users
    LEFT JOIN companies ON (users.state = companies.state)
    WHERE users.id = xxx

此时,两个 state 字段应该是被建过索引的,而且应该是相当的类型,相同的字符集。
②业务上具有唯一特性的字段,即使是多个字段的组合,也必须建成唯一索引。
③在 varchar 字段上建立索引时,必须指定索引长度,没必要对全字段建立索引,根据实际文本区分度决定索引长度即可。
④根据最左原则,不要使用%xxx%%xxx的形式,而是xxx%,只有这个才会使用索引(当前前提是该字段创建了索引)。
⑤利用覆盖索引来进行查询操作,避免回表。能够建立索引的种类:主键索引、唯一索引、普通索引,而覆盖索引是一种查询的一种 效果,用explain的结果,extra列会出现:using index。
⑥建组合索引的时候,区分度最高的在最左边。

参考:阿里巴巴Java开发手册v1.2.0


其他
NULL columns require additional space in the row to record whether their values are NULL. 
For MyISAM tables, each NULL column takes one bit extra, rounded up to the nearest byte.
①select * from A where exists (select * from B where B.id = A.id);
②select * from A where A.id in (select id from B);
①的执行可以表述为
对外表A中所有记录进行循环,每次循环中对内表B进行查询(如果当前行符合子条件,则选出),主要使用B中的索引。

参考:数据库性能优化之SQL语句优化深入研究mysql exists与in的性能及效率


全文思路参考
MYSQL性能优化的最佳20+条经验
20180226--更新对explainid的解释

上一篇 下一篇

猜你喜欢

热点阅读