mysql优化之sql优化

首先声明,非本人同意不得转载!!!

SQL查询优化

 

一、优化数据访问

1. 确认应用程序是否在检索大量超过需要的数据。通常是访问的行太多,但也可能是访问的列太多

2. 确认MySQL服务器层是否在分析大量超过需要的数据行。

 

优化数据的访问(减少无效的数据检索)

 

二、重构查询方式

1. 一个复杂查询还是多个简单查询

2. 切分查询

3. 分解关联查询

 

重构查询的方式(将大而复杂的SQL进行重构为小而简单的SQL)

 

三、查询缓存

查询缓存是要付出代价的,对查询的性能有很大影响,但如果发现付出的代价大于带来的好处,可以考虑关闭查询缓存。默认是关闭的

 

当开启查询缓存后,所有以SEL开头的语句都会判断查询缓存中是否有缓存结果。如果没有再进行SQL解析、执行。 当返回结果时会判断是否可以进行缓存,如果有特殊函数则不进行缓存结果。

 

查询缓存的消耗:

1. 检查缓存是否命中

2. 对查询结果进行缓存

3. 修改数据使得缓存失效

 

查询缓存结果是存储在内存中的,通过几个参数进行分配内存资源

Query_cache_size:查询缓存内存空间总大小

Query_cache_min_res_unit:内存最小单位

 

内存的分配是有MySQL服务器进行管理的,系统分配内存的操作只在初始化的时候进行分配一次。

 

查询缓存会导致碎片的情况:

1. 多个查询同时进行结果缓存时,两个查询结果之间回收掉未使用的内存空间。

2. 某个缓存失效时

 

实际情况很难评估查询缓存是否真正能够带来性能上的提升,而且对于性能瓶颈不在查询上的系统(如:网络传输瓶颈),查询缓存作用很小。

 

 

查询缓存是否能够发挥作用:

1. 理论上可以观察打开你会关闭查询缓存时,系统的效率来决定是否开启。

大部分情况下,全局平均效率不能反映真实情况。

2. 查询缓存命中率

计算公式:Qcache_hits/(Qcache_hits+Com_select)

很难判断命中率多高是合适的。如果查询缓存能够带来效率提升,大于查询缓存带来的资源消耗,30%的命中率也是对系统有很好的性能提升。

3. 命中写入比例(Qcache_hits和Qcache_inserts的比值)

通常最少大于3:1,最好能打到10:1

 

 

查询缓存配置:

query_cache_type:OFF/ON/DEMAND。DEMAND表示只有在查询语句中明确写明SQL_CACHE的语句才放入查询缓存。

query_cache_size:总内存空空间,必须是1024的整数倍

query_cache_min_res_unit:分配内存块的最小单位

query_cache_limit:能够缓存的最大查询结果。如果大于这个值,则不进行缓存。如果明确知道查询结果大于这个值,可以使用SQL_NO_CACHE,减少资源消耗

query_cache_wlock_invalidate:如果某个数据表被其他连接锁住,是否仍然从查询缓存中返回结果。

 

减少碎片:无法完全避免碎片的产生,但是可以选择合适的

query_cache_min_res_unit,以减少碎片的大小。但是不能太小,太小则要进行更频繁的内存块申请操作。

合适大小计算公式:内存实际消耗(query_cache_size-Qcache_free_memory)/Qcache_queries_in_cache(缓存个数),计算平均每个查询缓存的大小

 

分析和配置查询缓存的流程图:

mysql优化之sql优化_第1张图片

 

 

通用查询缓存优化:

1.用多个小表替代一个大表对查询缓存有好处。

2.批量写入时只需要做一次缓存失效,相比单条写入效率更好。

3.因为缓存空间太大,在过期操作的时候可能会导致服务器僵死。

4.无法在数据库或者表级别控制查询缓存,但是可以通过SQL_CACHE和SQL_NO_CACHE来控制某个SELECT语句是否需要进行缓存。

5.对写密集型应用来说,直接禁用查询缓存性能更好。

6.如果不想所有查询都进入缓存,可以设置query_cache_type为DEMAND。

 

四、查询优化器提示

HIGH_PRIORITY 和 LOW_PRIORITY:

告诉MySQL,当多个语句同时访问某一个表的时候,哪些语句的优先级相对高一些、哪些相对低一些。如果是HIGH_PRIORITY则会调整到所有正在等待表锁 以便修改数据的语句之前。针对有表锁的引擎有效

 

DELAYED:

立即响应给客户端,只对INSER和REPLACE有效。并非所有引擎都支持,而且会导致函数LAST_INSERT_ID()无效。

 

STRAIGHT_JOIN:

放在SELECT关键字后面,用于固定查询中表的关联顺序按照语句的顺序进行。

 

SQL_SMALL_RESULT和SQL_BIG_RESULT:

对SELECT语句有效,告诉MySQL优化去对GROUP BY和DISTINCT查询如何使用临时表排序,SQL_SMALL_RESULT表示结果集很小,在内存的临时表排序。反之则很大,用磁盘临时表排序

 

SQL_BUFFER_RESULT:

是一种缓存策略,将查询结果放到一个临时表,消耗服务器内存。会尽快的释放表锁

 

SQL_CACHE和SQL_NO_CACHE:

查询结果是否进行缓存

 

FOR UPDATE:

对查询加锁提示 select * from test for update;

 

USE INDEX\IGNORE INDEX和FORCE INDEX:

USE INDEX :指定使用的索引

IGNORE INDEX :忽略指定索引

FORCE INDEX :与use index基本相同,不过会告诉优化器,全表扫描的代价高于索引扫描。

 

 

五、优化特定类型的查询

1. Count()

使用近似值:执行计划中的值

汇总表

2. 关联查询

确保on或者USING子句中的列上有索引。

在创建索引的时候要考虑到关联的顺序。

关联查询也可以使用组合索引

3. Group BY

如果需要对关联查询做分组,那通常采用查找表的标识列分组的效率会比其他列更高。

4. Limit

尽可能的使用索引覆盖扫描,而不是查询所有的列,然后根据需要做一次关联操作再返回所需的列。

"延迟关联"将大大提升查询效率,使MySQL扫描尽可能少的页,获取需要访问的记录后再根据关联列回原表查询需要的所有列。

5. UNION

UNION与UNION ALL的差别,union all不再创建临时表,这样在联合查询时会减少I/O开销

你可能感兴趣的:(mysql优化之sql优化)