应用优化方式
? 设计合理的数据表结构:适当的数据冗余 ? 对数据表建立合适有效的数据库索引 ? 数据查询:编写简洁高效的SQL语句
表结构设计原则
? 选择合适的数据类型:如果能够定长尽量定长
? 使用 ENUM 而不是 VARCHAR,ENUM类型是非常快和紧凑的,在实际上,其保存的是 TINYINT,但其外表上显示为字符串。这样一来,用这个字段来做一些选项列表变得相当的完美 。
? 不要使用无法加索引的类型作为关键字段,比如 text类型
? 为了避免联表查询,有时候可以适当的数据冗余,比如邮箱、姓名这些不容易更改的数据
? 选择合适的表引擎,有时候 MyISAM 适合,有时候InnoDB适合
? 为保证查询性能,最好每个表都建立有 auto_increment字段, 建立合适的数据库索引
索引建立原则
? 一般针对数据分散的关键字进行建立索引,比如ID、QQ,像性别、状态值等等建立索引没有意义
? 字段唯一,最少,不可为null
? 对大数据量表建立聚集索引,避免更新操作带来的碎片。
? 尽量使用短索引,一般对int、char/varchar、date/time 等 类型的字段建立索引
? 需要的时候建立联合索引,但是要注意查询SQL语句的编写
? 谨慎建立 unique 类型的索引(唯一索引)
? 大文本字段不建立为索引,如果要对大文本字段进行检索,可以考虑全文索引
? 频繁更新的列不适合建立索引
? order by 字句中的字段,where 子句中字段,最常用的sql语句中字段,应建立索引。
? 唯一性约束,系统将默认为该字段建立索引。
? 对于只是做查询用的数据库索引越多越好,但对于在线实时系统建议控制在5个以内。
? 索引不仅能提高查询SQL性能,同时也可以提高带where字句的update,Delete SQL性能。
? Decimal 类型字段不要单独建立为索引,但覆盖索引可以包含这些字段。
? 只有建立索引以后,表内的行才按照特地的顺序存储,按照需要可以是asc或desc方式。
? 如果索引由多个字段组成将最用来查询过滤的字段放在前面可能会有更好的性能
sql优化,一般是2种,索引使用的好,以及其他方式
? 能够快速缩小结果集的 WHERE 条件写在前面,如果有恒量条件,也尽量放在前面
? 尽量避免使用 GROUP BY、DISTINCT 、OR、IN 等语句的使用,避免使用联表查询和子查询,因为将使执行效率大大下降
? 能够使用索引的字段尽量进行有效的合理排列,如果使用了联合索引,请注意提取字段的前后顺序
? 针对索引字段使用 >, >=, =, <, <=, IF NULL和BETWEEN 将会使用索引, 如果对某个索引字段进行 LIKE 查询,使用 LIKE ‘%abc%’ 不能使用索引,使用 LIKE ‘abc%’ 将能够使用索引
? 如果在SQL里使用了MySQL部分自带函数,索引将失效,同时将无法使用 MySQL 的 Query Cache,比如 LEFT(), SUBSTR(), TO_DAYS(),DATE_FORMAT(), 等,如果使用了 OR 或 IN,索引也将失效
? 使用 Explain 语句来帮助改进我们的SQL语句
? 不要在where 子句中的“=”左边进行算术或表达式运算,否则系统将可能无法正确使用索引
? 尽量不要在where条件中使用函数,否则将不能使用索引
? 避免使用 select *, 只取需要的字段
? 对于大数据量的查询,尽量避免在SQL语句中使用order by 字句,避免额为的开销,替代为使用ADO.NET 来实现。
?只关心需要的表和满足条件的数据
? 适当使用临时表或表变量
? 对于连续的数值,使用between代替in
? where 字句中尽量不要使用CASE条件
? 尽量不用触发器,特别是在大数据表上
? 更新触发器如果不是所有情况下都需要触发,应根据业务需要加上必要判断条件
? 使用union all 操作代替OR操作,注意此时需要注意一点查询条件可以使用聚集索引,如果是非聚集索引将起到相反的结果
? 当只要一行数据时使用 LIMIT 1
? 尽可能的使用 NOT NULL填充数据库
? 拆分大的 DELETE 或 INSERT 语句
? 批量提交SQL语句
SQL优化
1.大批量插入数据(Innodb)
1.load 命令导入数据的时候,适当的设置可以提高导入的效率。
2.主键顺序插入
3.关闭唯一性校验 先关,执行完,再开
4.手动提交事务
2.优化insert语句
1.尽量一次性插入
2.在事务中进行数据插入 不用一直开始关闭事务
3.数据有序插入 也就是根据id顺序插比较好
3.优化order by语句
1.第一种是通过对返回数据进行排序,也就是通常说的 filesort 排序,所有不是通过索引直接返回排序结果的排序都叫 FileSort 排序。
2.第二种通过有序索引顺序扫描直接返回有序数据,这种情况即为 using index,不需要额外排序,操作效率高。
3.了解了MySQL的排序方式,优化目标就清晰了:尽量减少额外的排序,通过索引直接返回有序数据。where 条件
和Order by 使用相同的索引,并且Order By 的顺序和索引顺序相同, 并且Order by 的字段都是升序,或者都是
降序。否则肯定需要额外的操作,这样就会出现FileSort。
4.Filesort 的优化
1.不能让Filesort消失,那就需要加快Filesort的排序操作。对于Filesort ,MySQL有两种排序算法
1.两次扫描算法:mysql 5之前的 根据条件取出排序字段和行指针信息,然后在排序区
sort buffer 中排序,如果sort buffer不够,则在临时表 temporary table中存储排序结果。
完成排序之后,再根据行指针回表读取记录,该操作可能会导致大量随机I/O操作。
2.一次扫描算法:一次扫描算法:一次性取出满足条件的所有字段,然后在排序区sort buffer中排序后直接输出结果集。
排序时内存开销较大,但是排序效率比两次扫描算法要高。
max_length_for_sort_data的大小和Query语句取出的字段总大小如果max_length_for_sort_data更大,那么使用第二种优化之后的算法
可以适当提高 sort_buffer_size 和 max_length_for_sort_data 系统变量,来增大排序区的大小,提高排序的效率。
4.优化group by 语句
分组前会使用到排序,我们可以手动将排序去掉
5.优化嵌套查询
少用子查询,因为子查询会在内存中创建临时表,多用连接查询
6.优化OR条件
1.对于包含OR的查询子句,如果要利用索引,则OR之间的每个条件列都必须用到索引,而且不能使用到复合索引;如果没有索引,则应该考虑增加索引
2.建议用union代替or
7.优化分页查询
1.越往后查询速度越慢
2.优化思路一:在索引上完成排序分页操作,最后根据主键关联回原表查询所需要的其他列内容。
select * from 表 a ,(select id from 表 order by id limit 200000,10) b where a.id=b.id
3.优化思路二:该方案适用于主键自增的表,可以把Limit 查询转换成某个位置的查询。
select * from 表 where id>2000000 limit 10
8.使用SQL提示:SQL语句中加入一些人为的提示来达到优化操作的目的。
1.USE INDEX 在表名后 加入 你想让 mysql 使用的 索引,可以让MySQL不再考虑其他可用的索引。
2.IGNORE INDEX
3.FORCE INDEX
为什么不用select *
1. select 的结果集,要作为数据 IO 到 上层应用,select 字段越少,数据量越少
2. 回表
|