Mysql查询性能优化(一)

一.查询的生命周期

    查询的生命周期大致可以按照顺序来看:从客户端,到服务器,然后再服务器上进行解析,生成执行计划,执行,并返回结果给客户端。其中“执行”是整个生命周期的最重要阶段,这其中包括了大量为了检索数据到存储引擎的调用和调用后的数据处理,包括排序,分组等。

    在完成这些任务的时候,查询需要在不同的地方花费时间,包括网络,CPU计算,生成统计信息和执行计划,锁等待(互斥等待)等操作,尤其是向底层存储引擎检索数据的调用操作,这些调用需要在内存操作,CPU操作和内存不足时导致的i/o操作上消耗时间。

二. 优化数据访问    

    1.减少不需要的数据的请求和只查询只需要的字段

    请求多余的数据会给MySQL服务器带来额外的负担,并增加网络开销,另外也会消耗应用服务器的CPU和内存资源。

    比如:“select * ”取出全部列的写法会让优化器无法完成索引的覆盖扫描这类优化,还会为服务器带来额外的i/o,内存和cpu的消耗

    2. MySQL是否在扫额外的记录

    MySQL衡量查询开销的三个指标:响应时间,扫描的行数,返回的行数

    在有索引的情况下查询一条数据所需要扫描的行数大约是10行左右,而在无索引的情况下查询就可能导致全表扫描,另外我们在查询中可以使用where条件来过滤不匹配的记录,这是在存储引擎层完成的。

三. 重构查询的方式

    1.一个复杂的查询还是多个简单的查询?MySQL从设计上让连接和断开连接都很轻量级,在返回一个小的查询结果方面都很高效。而且在某些版本的mysql桑,即时在一个通用服务器上,也能够运行每秒超过十万的查询,即时是一个千兆网卡也能轻松满足每秒超过2k次的查询。所以运行多个小查询现在已经不是大问题了。

    2. 切分查询:

    有时候对于一个大查询我们需要“分而治之”,将大查询切分成小查询,每个查询功能完全一样,只完成一小部分,每次只返回一小部分查询结果,比如说删除大量数据的例子:

rows_affected = 0
do{
   rows_affected = do_query(
"delece"from messages where created < date_sub(now(),interval 3 month)
)while rows_affected > 0

这样的做法可以尽可能的减少对MySQL的影响,而且把对服务器的一次性压力减少分散到一个很长的时间段中去。

3. 分解关联查询

   很多高性能的应用都会对关联查询进行分解。简单地,可以对每一个表进行一次单表查询,然后将结果在应用程序中进行关联。

    eg:

SELECT * FROM tag JOIN tag_post ON tag_post_id=tag_id JOIN post ON tag_post.post_id=post.id WHERE tag.tag = 'mysql';

    上面的这一条语句可以分解成下面的这些查询来代替:

    

SELECT * FROM tag WHERE tag = 'mysql';
SELECT * FROM tag_post WHERE tag_id = 1234;
SELECT * FROM post WHERE post.id in (123,456,567,9098,8904);

这样分解的好处是: 

1.让缓存的效率更高,例如上面已经缓存了ID为123,567,9098的内容,那么第三个查询的IN()中就可以几个id

2.将查询分解后,执行单个查询可以减少锁的竞争

3.用IN()代替关联查询,可以让MySQL按照ID顺序进行查询,这可能比随机的关联要更加高效

4.可以减少冗余记录的查询,在数据库中做关联查询,可能需要重复的访问一部分数据,从这点看,这样的重构还能减少网络和内存的消耗。

猜你喜欢

转载自blog.csdn.net/Rust94/article/details/80060882