原文:
http://blog.gqylpy.com/gqy/389
???????MySQL的性能优化包罗甚广:索引优化、查询优化、查询缓存、服务器设置优化、操作系统及硬件优化、应用层优化(web服务器、缓存)等等。本文提到的优化技巧更适用于开发人员,都是从网络上收集和自己整理的,主要是查询语句上面的优化,其它层面的优化技巧在此不做记录。
整理如下
- 合理创建索引
- count 的优化
- 避免使用不兼容的数据类型
- 索引字段上进行运算会使索引失效
- 尽量避免使用 !=、is null、is not null、in、not in 这样的操作符
- 尽量使用数字型字段
- 合理使用 exists、not exists 子句
- 能够用 between 的就不要用 in
- 能够用 distinct 的就不要用 group by
- 尽量不要使用 select info 语句,它会导致表锁,阻止其它用户访问该表
- 必要时强制查询优化器使用某个索引
- 消除对大型表行数据的顺序存取
- 程序中如果需要一次性对同一个表插入多条数据,应写成一条语句
查询的开销指标
- 执行时间
- 检查的行数
- 返回的行数
建立索引的几个准则
- 合理的建立索引能够加快数据读取效率,不合理的建立索引反而会拖慢数据的响应速度。
- 索引越多,更新数据的速度越慢。
- 尽量在采用 MyISAM 作为存储引擎的时候使用索引(因为MySQL以Btree存储索引),而不是 InnoDB 。但 MyISAM 不支持 Transcation。
- 当你的程序和数据结构/SQL语句已经优化到无法优化的程度,而程序的瓶颈并不能顺利解决,那就应该考虑使用诸如 memcached 这样的分布式缓存系统了。
- 习惯或强迫自己用 EXPLAIN 来分析你得SQL语句性能。
count的优化
比如,计算id大于5的城市,如下两种写法:
- seleft count(*) from world.city where id > 5;
- select (select count(*) from world.city) - count(*) from world.city where id <= 5;
???????当行数超过11时,1. 语句比 2. 语句扫描的行数要多,2. 语句只扫描6行,在此情况下,2. 语句比 1. 语句更有效率。当没有 where 语句的时候直接 select count(*) from world.city ,这样会更快,因为MySQL总是知道表的行数。
避免使用不兼容的数据类型...
例如 float和int、char和varchar、binary和varbinary 是不兼容的。 数据类型的不兼容可能会使优化器无法执行一些本来可以进行的优化操作。
- 在程序中,保证在实现功能的基础上,尽量减少对数据库的访问次数;
- 通过搜索参数,尽量减少对表的访问次数,最小化结果集,从而减轻网络负担;
- 能够分开的操作尽量分开处理,提高每次的响应速度;
- 在数据库窗口使用SQL时,尽量把使用的索引放在选择的首列;
- 算法的结构尽量简单;
- 在查询时,不要过多地使用统配符,例如 select * from table,要用到哪个字段,就写哪个字;
- 在可能的情况下尽量限制结果集行数,因为在某些情况下,用户是不需要那么多数据的;
- 不要在应用中使用数据库游标,虽然游标是非常有用的工具,但是比使用常规的、面向集的SQL语句需要更大的开销;
- 按照特定顺序提取数据的查找。
索引字段上进行运算会使索引失效
尽量避免在 where 子句中对字段进行函数或表达式操作,这将导致引擎放弃使用索引而进行全表扫描。如:select field from table where field / 2 = 10 应改为:select field from table where where field = 10 * 2 。
尽量避免使用 !=、<>、is null、is not null、in、not in 等这样的操作符
????????因为这会使系统无法使用索引,而只能直接搜索表中的数据,例如:select field from table where field != ‘xx%‘。优化器将无法通过索引来确定将要命中的行数,因此需要搜索该表的所有行,在 in 语句中能用 exists 语句代替的就是 exists 。
尽量使用数字型字段
????????一部分开发人员和数据库管理人员喜欢把包含数值信息的字段设计为字符型,这会降低查询和连接的性能,并会增加存储开销。这是因为引擎在处理查询和连接时会逐个比较字符串中的每一个字符,而数字型只需要比较一次就够了。
合理使用exists、not exists子句
- select sum(t1.f1) from t1 where (select count(*) from t2 where t2.f2 = t1.f2 > 0);
- select sum(t1.f1) from t1 where exists(select * from t2 where t2.f2 = t1.f2);
????????两者产生的效果是相同的,但是后者的效率显然要高于前者,因为后者不会产生大量锁定的表扫描或是索引扫描。如果你想校验表中是否存在某条记录,不要使用 count(*) ,那样效率会很低,而且浪费服务器资源。可以用 exists 代替。如:if (select count(*) from t where f = ‘x‘); 可以写成:if exists (select * from t where f = ‘x‘); 。
必要时强制查询器使用某个索引
????????例如:select * from table where nextprocess = 1 and processid in (8, 32, 48);,应改为:select * from table (index = ix_processid) where nextprocess = 1 and processid in (8, 32, 45);,此时查询优化器将会强制利用索引ix_processid执行查询。
原文:
http://blog.gqylpy.com/gqy/389
原文地址:https://www.cnblogs.com/mypath1/p/11405812.html