mysql 查询优化理解

来源:互联网 发布:宋茜演技 知乎 编辑:程序博客网 时间:2024/05/21 09:31

优化方法

该优化查询方法是在800W数据查询优化得出的总结
版本:mysql5.6,系统:cetnos7.1

普通优化

1、创建索引(根据业务关系,复合索引)
2、表分区(水平分区:根据查询的列来通过range水平分区,垂直分表:根据经常查询的条件新建一表(这个要结合索引来),不需要查询的条件再建一表,left join即可)
3、读写分离,读myisam,写innodB
4、php+Sphinx建立高效搜索

深入优化

1、对于索引优化这里,如果查询的时候出现limit:
原文链接
1. 直接用limit start, count分页语句, 也是我程序中用的方法:

select * from product limit start, count
当起始页较小时,查询没有性能问题,我们分别看下从10, 100, 1000, 10000开始分页的执行时间(每页取20条), 如下:

select * from product limit 10, 20 0.016秒
select * from product limit 100, 20 0.016秒
select * from product limit 1000, 20 0.047秒
select * from product limit 10000, 20 0.094秒

我们已经看出随着起始记录的增加,时间也随着增大, 这说明分页语句limit跟起始页码是有很大关系的,那么我们把起始记录改为40w看下(也就是记录的一般左右)

select * from product limit 400000, 20 3.229秒

再看我们取最后一页记录的时间
select * from product limit 866613, 20 37.44秒
但是在这里我用了同样的查询方法优化,我发现在没有添加索引的情况下直接查询比用了索引的查询速度回更加的快,我分析是因为添加了索引之后,不仅进行了索引查询还进行了全表扫面或者表的大部分数据的扫描,然后每条数据通过索引查询出来的记录地址去寻址
像这种分页最大的页码页显然这种时间是无法忍受的。

从中我们也能总结出两件事情:
1)limit语句的查询时间与起始记录的位置成正比
2)mysql的limit语句是很方便,但是对记录很多的表并不适合直接使用。

  1. 对limit分页问题的性能优化方法

利用表的覆盖索引来加速分页查询
我们都知道,利用了索引查询的语句中如果只包含了那个索引列(覆盖索引),那么这种情况会查询很快。

因为利用索引查找有优化算法,且数据就在查询索引上面,不用再去找相关的数据地址了,这样节省了很多时间。另外Mysql中也有相关的索引缓存,在并发高的时候利用缓存就效果更好了。

在我们的例子中,我们知道id字段是主键,自然就包含了默认的主键索引。现在让我们看看利用覆盖索引的查询效果如何:

这次我们之间查询最后一页的数据(利用覆盖索引,只包含id列),如下:
select id from product limit 866613, 20 0.2秒
相对于查询了所有列的37.44秒,提升了大概100多倍的速度

那么如果我们也要查询所有列,有两种方法,一种是id>=的形式,另一种就是利用join,看下实际情况:

SELECT * FROM product WHERE ID > =(select id from product limit 866613, 1) limit 20
查询时间为0.2秒!

另一种写法
SELECT * FROM product a JOIN (select id from product limit 866613, 20) b ON a.ID = b.id
查询时间也很短!

还有一种写法是不通过分页序号查询页面,而是通过下面这种方式

使用”上一页”和”下一页”进行分页:
上一页(id:60~41)
当前页(id:40~21)
下一页(id:20~01)

上一页(新文章20篇):
//page.php?id=40 正数表示上一页新文章,这里的40表示当前页最上面的文章的ID.
SELECT * FROM posts WHERE id > 40 ORDER BY id ASC LIMIT 20;
这里得到的是升序ID序列,PHP使用array_reverse反转数组实现降序输出即可.

下一页(旧文章20篇):
//page.php?id=-21 负数表示下一页旧文章,这里的21表示当前页最下面的文章的ID.
SELECT * FROM posts WHERE id < 21 ORDER BY id DESC LIMIT 20;
觉得负数不好看的话,可以额外加一个参数,比如 page.php?id=21&next

结语:
在这里感觉如果分页达到上万的时候就不应采取分页查询的方式来进行了,实际业务逻辑中也不会说分页到1W的数据量的级别,不过这里纯粹是为了测试一下数据库的查询优化。

转载:

  1. MySQL大数据量分页查询方法及其优化