Query优化的基本思路和原则
1. 优化更需要优化的Query;
高并发低消耗(相对)的Query 对整个系统的影响远比低并发高消耗的Query 大
2. 只取出自己需要的Columns;
对于任何Query,返回的数据都是需要通过网络数据包传回给客户端,如果取出的Column 越多,需要传输的数据量自然会越大,不论是从网络带宽方面考虑还是从网络传输的缓冲区来看,都是一个浪费。
3. 仅仅使用最有效的过滤条件;
很多人在优化Query 语句的时候很容易进入一个误区,那就是觉得WHERE 子句中的过滤条件越多越好,实际上这并不是一个非常正确的选择。其实我们分析Query 语句的性能优劣最关键的就是要让他选择一条最佳的数据访问路径。
举例
需求: 查找某个用户在所有group 中所发的讨论message 基本信息。
场景:
1、知道用户ID 和用户nick_name
2、信息所在表为group_message
3、group_message 中存在用户ID(user_id)和nick_name(author)两个索引
方案一:将用户ID 和用户nick_name 两者都作为过滤条件放在WHERE 子句中来查询,执行语句如下: SELECT * FROM group_message WHERE user_id = 1 AND author='1111111111‘
方案二:仅仅将用户ID 作为过滤条件放在WHERE 子句中来查询,查询语句如下: SELECT * FROM group_message WHERE user_id = 1
方案三:仅将用户nick_name 作为过滤条件放在WHERE 子句中来查询,查询语句如下: SELECT * FROM group_message WHERE author = '1111111111‘
4. 尽可能避免复杂的Join 和子查询;
举例: SELECT * FROM T1 WHERE ID IN (10,11,12,13,14) 改成: SELECT * FROM T1 WHERE ID BETWEEN 10 AND 14 因为IN会使系统无法使用索引而只能直接搜索表中的数据。
5. Prepared Statements;
一个相同的查询被使用多次的时候,你可以给这些Prepared Statements定义一些参数,而MySQL只会解析一次,这会为你带来可观的性能优势。
6. 无缓冲的查询;
对那些执行频率低,提取数据多的查询语句,可以使用无缓冲查询。
举例: SELECT SQL_NO_CACHE m.id,m.subject,c.content FROM group_message m,group_message_content c WHERE m.group_id = 1 AND m.id = c.group_msg_id;
7. 使用索引;
索引就是加快检索表中数据的方法。数据库的索引类似于书籍的索引。在书籍中,索引允许用户不必翻阅完整个书就能迅速地找到所需要的信息。在数据库中,索引也允许数据库程序迅速地找到表中的数据,而不必扫描整个数据库。
索引分类 (
1)普通索引 这是最基本的MySQL数据库索引,它没有任何限制。它有以下几种创建方式: 创建索引 CREATE INDEX indexName ON mytable(username(length)); 修改表结构 ALTER mytable ADD INDEX [indexName] ON (username(length))
(2)唯一索引 它与前面的普通索引类似,不同的就是:MySQL数据库索引列的值必须唯一,但允许有空值。如果是组合索引,则列值的组合必须唯一。 CREATE UNIQUE INDEX indexName ON mytable(username(length)) ALTER mytable ADD UNIQUE [indexName] ON (username(length))
(3)主键索引 它是一种特殊的唯一索引,不允许有空值。一般是在建表的时候同时创建主键索引: CREATE TABLE mytable( ID INT NOT NULL, username VARCHAR(16) NOT NULL, PRIMARY KEY(ID) ); 当然也可以用 ALTER 命令。记住:一个表只能有一个主键。
(4)组合索引
索引的优点 :一个没有索引的数据表就是一个无序的数据行集合,假如要查询一个数据表的某一行,就需要检查数据表的每一行,进行全表扫描,如果数据表很大,但是仅有少数几个记录与搜索条件匹配,那么工作过程就很慢,效率很低。
索引的缺点:索引加快了查询速度,但是却降低了在带索引的数据列里插入删除以及修改数值的速度。索引要占据磁盘空间,多个索引会占据更大的空间。