优化嵌套查询

嵌套查询(子查询)可以使用SELECT语句来创建一个单列的查询结果,然后把这个结果作为过滤条件用在另一个查询中。嵌套查询写起来简单,也容易理解。但是,有时候可以被更有效率的连接(JOIN)替代。

现在假如要找出从来没有在网站中消费的客户,也就是查询在客户customer表中但是不在支付payment表中的客户信息。

嵌套查询:

explain select * from customer where customer_id not in (select customer_id from payment);

连接改写:

explain select * from customer a left join payment b on a.customer_id = b.customer_id where b.customer_id is null;

画外音:连接查询效率更高的原因,是因为MySQL不需要在内存中创建临时表来完成这个逻辑上需要两个步骤的查询工作;并且Not exists表示MYSQL优化了LEFT JOIN,一旦它找到了匹配LEFT JOIN标准的行, 就不再搜索了。

优化分页查询

在MySQL中做分页查询,MySQL 并不是跳过 offset 行,而是取 offset+N 行,然后返回放弃前 offset 行,返回 N 行,那当 offset 特别大的时候,效率就非常的低下。例如“limit 1000,20”,此时MySQL排序出前1020条数据后仅仅需要第1001到1020条记录,前1000条数据都会被抛弃,查询和排序的代价非常高。由此可见MySQL的分页处理并不是十分完美,需要我们在分页SQL上做一些优化,要么控制返回的总页数,要么对超过特定阈值的页数进行 SQL 改写

画外音:控制返回的总页数并不是那么靠谱,毕竟每页的数据量也不能过大,数据多起来之后,控制返回的总页数就变的不现实了。所以还是要对超过特定阈值的页数进行 SQL 改写

现在假设要对电影表film排序后取某一页数据

explain select * from film order by title limit 50,5;

可以看到优化器实际上做了全表扫描,处理效率不高。

第一种优化思路

在索引上完成排序分页的操作,最后根据主键关联回表查询所需要的其他列内容。

画外音:此处涉及到了SQL优化的两个重要概念,索引覆盖和回表,我在前面的文章中详细介绍过这两个概念。通过索引覆盖在索引上完成扫描和排序(索引有序),最后通过主键(InnoDB引擎索引会通过主键回表)回表查询,最大限度减少回表查询的I/O次数。

explain select * from film a inner join (select film_id from film order by title limit 50,5)b on a.film_id = b.film_id;

第二种优化思路

把LIMIT查询转换成某个位置的查询,减少分页翻页的压力。

假设现在每页10条数据,要取第42页的数据。

explain select * from film order by title limit 410,10;

现在需要多传一个参数,就是上一页(第41页)的最后一条数据的主题title,

SQL可以改写为:

explain select * from film where title>'HOLES BRANNIGAN' order by title limit 10;

这样就把LIMIT m,n 转换成了LIMIT n的查询,但是这种方案只适合在不会出现重复值的特定环境,否则分页结果可能会丢失数据。

总结

对于嵌套查询和分页查询的优化,归根结底就是遵循SQL优化原则之一——减少回表查询的I/O次数。对于分页查询优化,更建议使用第一种优化方案,性能更好,稳定性更高。

参考

《深入浅出MySQL》

作者:CoderFocus

微信公众号:

声明:本文为博主学习感悟总结,水平有限,如果不当,欢迎指正。如果您认为还不错,不妨点击一下下方的【推荐】按钮,谢谢支持。转载与引用请注明作者及出处。

MySQL——优化嵌套查询和分页查询的更多相关文章

  1. SQL语句or查询,union all查询,分页查询,分组,AND查询

    一.OR查询 1.在AND多个筛选条件和一个or条件时,如果没有括号包裹,or会就近原则包裹之后的所有and条件,也就是同级的多个and条件只能对,or条件的一边起作用 2.如果or条件两边的筛选条件 ...

  2. SQL Server -- 回忆笔记(四):case函数,索引,子查询,分页查询,视图,存储过程

    SQL Server知识点回忆篇(四):case函数,索引,子查询,分页查询,视图,存储过程 1. CASE函数(相当于C#中的Switch) then '未成年人' else '成年人' end f ...

  3. Linq高级查询,分页查询及查询分页结合

    一.高级查询与分页查询 1.以...开头    StartsWith Repeater1.DataSource=con.Users.Where(r=>r.Nickname.StartsWith( ...

  4. Mysql系列(五)—— 分页查询及问题优化

    一.用法 在Mysql中分页查询使用关键字limit.limit的语法如下: SELECT * FROM tbl LIMIT 5,10; # Retrieve rows 6-15 limit关键字带有 ...

  5. MySQL 百万级数据量分页查询方法及其优化

    方法1: 直接使用数据库提供的SQL语句 语句样式: MySQL中,可用如下方法: SELECT * FROM 表名称 LIMIT M,N 适应场景: 适用于数据量较少的情况(元组百/千级) 原因/缺 ...

  6. mysql limit查询(分页查询)探究

    MySQL的Limit子句 LIMIT offset,length Limit子句可以被用于强制 SELECT 语句返回指定的记录数.Limit接受一个或两个数字参数.参数必须是一个整数常量.如果给定 ...

  7. MYSQL优化派生表(子查询)在From语句中的

    Mysql 在5.6.3中,优化器更有效率地处理派生表(在from语句中的子查询): 优化器推迟物化子查询在from语句中的子查询,知道子查询的内容在查询正真执行需要时,才开始物化.这一举措提高了性能 ...

  8. mysql优化---订单查询优化:异步分页处理

    订单分页查询: 老的代码是顺序执行查询数据和计算总记录数,但是如果条件复杂的话(比如关联子表)查询的时间要超过20s种 public static PagedList<Map<String ...

  9. Oracle子查询相关内容(包含TOP-N查询和分页查询)

    本节介绍Oracle子查询的相关内容: 实例用到的数据为oracle中scott用户下的emp员工表,dept部门表,数据如下: 一.子查询 1.概念:嵌入在一个查询中的另一个查询语句,也就是说一个查 ...

随机推荐

  1. USB插入电脑的硬件检测和枚举流程

    USB协议定义了设备的6种状态,仅在枚举过程种,设备就经历了4个状态的迁移:上电状态(Powered),默认状态(Default),地址状态(Address)和配置状态(Configured)(其他两 ...

  2. python中匿名函数lambda

    简单来说,编程中提到的 lambda 表达式,通常是在需要一个函数,但是又不想费神去命 名一个函数的场合下使用,也就是指匿名函数. 先看它的几个用法: map( lambda x: x*x, [y f ...

  3. Maven classifier 元素妙用

    首先来看这么一个依赖 <dependency> <groupId>net.sf.json-lib</groupId> <artifactId>json- ...

  4. Kaggle项目实战一:Titanic: Machine Learning from Disaster

    项目地址 https://www.kaggle.com/c/titanic 项目介绍: 除了乘客的编号以外,还包括下表中10个字段,构成了数据的所有特征 Variable Definition Key ...

  5. 使用 Linux 自带的 logrotate 程序来控制日志文件尺寸

    1. 编写配置文件,内容如下(以 Amadeus 系统为例): 编写配置文件,放在 /etc/logrotate.d/xxxx 下,其中 xxxx 是自己取的名字,无需后缀.例如 Amadeus 系统 ...

  6. 【杂谈】线程中断——Interrupt

    前言 以前有一个错误的认识,以为中断操作都会抛出异常,后来才发现并不是这样,所以今天就来做一个关于中断的总结. 如何关闭线程 已被弃用的Stop方法 早期,Thread类中有一个stop方法,用于强行 ...

  7. 第一个Quartz程序 (二)

    1 我们使用maven项目 2 创建一个job类,在execute()方法里写上业务逻辑代码. 3 在另外一个类中创建触发器,调度器,并且绑定job. 首先在项目的pom.xml引入需要的jar包. ...

  8. JavaWeb学习 (七)————HttpServletResponse对象(一)

    一.HttpServletResponse对象介绍

  9. Mybatis之基于XML的调用存储过程与手动回滚事务

    一.调用存储过程 一.返回单个值 1.存储过程准备 这里先创建一个存储过程,传入参数为age,传出参数为count.然后先测试一下是否正确. CREATE DEFINER=`root`@`localh ...

  10. [转]VR原理讲解及开发入门

    本文转自:http://www.52vr.com/article-661-1.html 本文是作者obuil根据多年心得专门为想要入门的VR开发者所写,由52VR网站提供支持.   1. VR沉浸感和 ...