SQL语句优化实践

减少查询的影响结果集,避免出现全表扫描。

影响结果集是SQL优化的核心。影响结果集不是查询返回的记录数,而是查询所扫描的结果数。通过Explain或Desc分析SQL,rows列的值即为影响结果集(还可以通过慢查询日志的Rows_examined后面的数字得到)。

以下是我常用的一些SQL优化策略:

  1. 去掉不必要的查询和搜索。其实在项目的实际应用中,很多查询条件是可有可无的,能从源头上避免的多余功能尽量砍掉,这是最简单粗暴的解决方案。
  2. 合理使用索引和复合索引。建索引是SQL优化中最有效的手段。查找、删除、更新以及排序时常用的字段可以适当建立索引。不过要注意,单条查询不能同时使用多个索引,只能使用一个索引。查询条件较多时,可以使用多个字段合并的复合索引。切记,使用复合索引时,查询条件的字段顺序需要与复合索引的字段顺序保持一致。
  3. 谨慎使用not in等可能无法使用索引的条件。索引也不是什么时候都可以发挥作用的,当出现"not in","!=","like '%xx%'","is null"等条件时,索引是无效的。使用这些条件的时候,请放到能有效使用索引的条件的右边。设计表结构时,个人建议尽可能用int类型代替varchar类型,int类型部分时候可以通过大于或小于代替"!="等条件,同时也方便满足一些需要按类型排序的需求,至于可读性的问题,完善好数据库设计文档才是明智的选择。同时建议把所有可能的字段设置为"not null",并设置默认值,避免在where字句中出现"is null"的判断。
  4. 不要在where子句中的“=”左边进行函数、算术运算或其他表达式运算,否则系统将无法正确使用索引。尽可能少用MySQL的函数,类似Now()完全可以通过程序实现并赋值,部分函数也可以通过适当的建立冗余字段来间接替代。
  5. 在where条件中使用or,可能导致索引无效。可用 "union all" 或者 "union" (会过滤重复数据,效率比前者低) 代替,或程序上直接分开两次获取数据再合并,确保索引的有效利用。
  6. 不使用select * ,倒不是能提高查询效率,主要是减少输出的数据量,提高传输速度。
  7. 避免类型转换,这里所说的“类型转换”是指where子句中出现字段的类型和传入的参数类型不一致的时候发生的类型转换。
  8. 分页查询的优化。页数比较多的情况下,如limit 10000,10 影响的结果集是10010行,查询速度会比较慢。推荐的解决方案是:先只查询主键select id from table where .. order by .. limit 10000,10(搜索条件和排序请建立索引),再通过主键去获取数据。
  9. 统计相关的查询。影响结果集往往巨大,且部分SQL语句本身已经难以优化。因此,应避免在业务高峰期执行统计相关的查询,或者仅在从库中执行统计查询。部分统计数据,可以通过冗余的数据结构保存,同时建议把数据先保存在内存、缓存中(如redis),再按一定策略写入数据库。

附常用sql语句


不使用任何连表查询,通过分库和分表实现负载均衡。

随着数据量的增加,连表操作往往会导致影响结果集大增,从SQL优化的层面已经解决不了问题了。

此时,分库和分表是解决数据库性能压力的最优选择(具体分库和分表的方案通常结合实际业务的应用场景来确定,此处略过)。这里重点谈,如何更好的实现或者过渡到分库、分表的分布式数据库架构。

核心点就是必须先去除数据表之间的关联,即不用外键,不使用任何连表查询。为了确保不进行连表操作,在设计数据库表结构的时候,就需要设计适度冗余的字段来达到不连表的目的。

对于一些操作日志、支付记录等,设计一些记录用户信息的字段,个人认为其实不能算冗余,毕竟用户信息往往会更改,但是这种类似操作日志的表确实是需要记录用户操作时的信息,并且不需要在用户更新信息时同步更新。

实际开发中,为了实现不进行连表而冗余的字段,往往是需要在原表更新数据的时候同步更新冗余字段的数据的,如果应用层没有对数据表操作做合理封装,这往往是个棘手的问题,也不方便维护。

当然,现在主流的应用框架,一般采用orm的方式处理数据表,所以问题不大。相反,不连表事实上还可以提高开发效率,比如通过用户ID获取用户姓名操作,如果不连表就可以确保各个业务模块都通过同样的方式去获取用户姓名,调用同一个封装好的方法,这样,就能很方便的统一在应用层加入缓存机制或添加统一的业务逻辑。

同时如果要对用户表进行分库分表,通过应用层程序就可以简单平滑的实现。

使用Innodb。

关于Innodb和Myisam对比,我就不多说了。Myisam的表级锁是致命问题,考虑到MySQL已经默认使用Innodb作为数据库引擎,个人建议大部分情况可以直接使用Innodb,其他引擎这里就不详细讨论了。

使用缓存。

1) 尽可能在程序上实现常用数据的缓存,目前主流的应用框架应该都能快速实现缓存的需求。如果在程序上没有实现数据缓存,开启数据库的query cache也是缓解数据库压力的方式之一,如果确认使用,记得定时清理碎片flush query cache。

附常用sql语句

1.创建数据库:create database 数据库名 【charset 数据编码名】 【collate 排序规则名】;
2.修改数据库:alter database 数据库名 【charset 新的数据编码名】 【collate 新的排序规则名】
3.删除数据库:drop database 【if exists】 数据库名;
4.使用(进入)某数据库:use 数据库名;
5.显示所有数据库名:show databases;
6.修改数据表的字段的值:update 表名 set 字段='要修改后的值' where 定位字段='值' 例:update
7.显示所有数据库: show databases;
8.显示某个数据库的所有表:show full tables from mblogs where table_type = 'base table';
9.显示数据库编码:show charset
10.创建表单:create table mblogs. m_linkss(id int(4) not null auto_increment,link_name varchar(60),primary key (id))engine=myisam charset=utf8 collate=utf8_general_ci
11.删除表:drop table mblogs.m_linkss;
12.修改表是指修改表的结构或特性。理论上创建一个表能做到的事情,修改表也能做到。修改表有二三十项修改项,包括增删改字段,增删索引,增删约束,修改表选项等等。举例如下:
13.添加字段:alter table 表名 add [column] 新字段名 字段类型 [字段属性列表];
14.修改字段(并可改名):alter table 表名 change [column] 旧字段名 新字段名 新字段类型 [新字段属性列表];
15.修改字段(只改属性):alter table 表名 modify [column] 字段名 新字段类型 [新字段属性列表];
16.删除字段:alter table 表名 drop [column] 字段名;
17.添加普通索引: alter table 表名 add index [索引名] (字段名1[,字段名2,...]);
18.添加主键索引(约束):alter table 表名 add primary key (字段名1[,字段名2,...]);
19.添加外键索引(约束):alter table 表名1 add foreign key (字段1,[,字段名2,...]) references 表名2(字段1,[,字段名2,...]);
20.添加唯一索引(约束):alter table 表名 add unique (字段名1[,字段名2,...]);
21.添加字段默认值(约束):alter table 表名 alter [column] 字段名 set default 默认值;
22.删除字段默认值(约束):alter table 表名 alter [column] 字段名 drop default;
23.删除主键:alter table 表名 drop primay key;#每一个表最多只能有一个主键
24.删除外键:alter table 表名 drop foreign key 外键名;
25.删除索引:alter table 表名 drop index 索引名;
26.修改表名:alter table 表名 rename [to] 新表名;
27.修改表选项:alter table 表名 选项名1=选项值1,选项名2=选项值2,...;
28.修改数据库密码:update `pro_systemuser` set password=MD5(123456) where name='admin';

原文地址:https://www.cnblogs.com/hellohell/p/6208466.html