MySQL查询中LIMIT的大offset导致性能低下浅析

前言

我们大家都知道,mysql查询使用select命令,配合limit,offset参数可以读取指定范围的记录,但是offset过大影响查询性能的原因及优化方法

我们在业务系统中难免少不了分页的需求。想到分页的时候,大家肯定会想到使用SQL中的LIMIT来实现。但是,如果不正确的使用LIMIT会导致性能问题(SQL执行得很慢、有可能会拖垮服务器),也会被领导批的;所以,我们来看看如何正确地使用LIMIT。

下面话不多说了,来一起看看详细的介绍吧

LIMIT OFFSET, ROW_COUNT 实现分页

存在性能问题的方式

SELECT * FROM myTable ORDER BY `id` LIMIT 1000000, 30 

写出这样SQL语句的人肯定心里是这样想的:MySQL数据库会直接定位到符合条件的第1000000位,然后再取30条数据。
然而,实际上MySQL不是这样工作的。

LIMIT 1000000, 30 的意思是:扫描满足条件的1000030行,扔掉前面的1000000行,然后返回最后的30行。

较好的方式

SELECT t.*
FROM (
  SELECT id
  FROM myTable
  ORDER BY
    id
  LIMIT 1000000, 30
  ) q
JOIN myTable t
ON  t.id = q.id

大概的原理是:

  • 子查询只用到了索引列,没有取实际的数据,所以不涉及到磁盘IO,所以即使是比较大的 offset,查询速度也不会太差。

对具体的原理分析感兴趣的朋友可以看看这篇文章:MySQL ORDER BY / LIMIT performance: late row lookups

后记

未完待续。

参考资料

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对我们的支持。

(0)

相关推荐

  • 对MySQL几种联合查询的通俗解释

    表a aid adate 1 a1 2 a2 3 a3 表b bid bdate 1 b1 2 b2 4 b4 两个表a.b相连接,要取出id相同的字段. select * from a inner join b on a.aid = b.bid 这是仅取出匹配的数据. 此时的取出的是: 1 a1 b1 2 a2 b2 那么left join 指: select * from a left join b on a.aid = b.bid 首先取出a表中所有数据,然后再加上与a.b匹配的的数据.

  • mysql多表联合查询返回一张表的内容实现代码

    今天在使用mysql语句的时候老是报错,语句如下: Sql代码 复制代码 代码如下: SELECT sapcle FROM SellEnterpriseBaseInfor sebie,SellEnterpriseBaseInforVer sebive,SellApplyPermitChangeList sapcle WHERE 1=1 AND sebie.iVerID = sebive.id AND sapcle.iEnterpriseBaseInforID=sebive.id AND sapc

  • Mysql联合查询UNION和UNION ALL的使用介绍

    一.UNION和UNION ALL的作用和语法 UNION 用于合并两个或多个 SELECT 语句的结果集,并消去表中任何重复行.UNION 内部的 SELECT 语句必须拥有相同数量的列,列也必须拥有相似的数据类型.同时,每条 SELECT 语句中的列的顺序必须相同.SQL UNION 语法: 复制代码 代码如下: SELECT column_name FROM table1UNIONSELECT column_name FROM table2 注释:默认地,UNION 操作符选取不同的值.如

  • 详解Mysql多表联合查询效率分析及优化

    1. 多表连接类型 1. 笛卡尔积(交叉连接) 在MySQL中可以为CROSS JOIN或者省略CROSS即JOIN,或者使用','  如: SELECT * FROM table1 CROSS JOIN table2 SELECT * FROM table1 JOIN table2 SELECT * FROM table1,table2 由于其返回的结果为被连接的两个数据表的乘积,因此当有WHERE, ON或USING条件的时候一般不建议使用,因为当数据表项目太多的时候,会非常慢.一般使用LE

  • Mysql联合查询UNION和Order by同时使用报错问题的解决办法

    因此,常常出现这样的错误 复制代码 代码如下: select * from [IND] where INDID>10unionselect * from [IND] where INDID<9 目前为止,还没有出现问 之后,也许有人会用到类似的查询 复制代码 代码如下: select * from [IND] where INDID>10 order by INDID descunionselect * from [IND] where INDID<9 order by INDID

  • Mysql查询正在执行的事务以及等待锁的操作方式

    使用navicat测试学习: 首先使用set autocommit = 0;(取消自动提交,则当执行语句commit或者rollback执行提交事务或者回滚) 在打开一个执行update 查询 正在执行的事务: SELECT * FROM information_schema.INNODB_TRX 根据这个事务的线程ID(trx_mysql_thread_id): 从上图看出对应的mysql 线程:一个94362 (第二个正在等待锁)另一个是93847(第一个update 正在执行 没有提交事务

  • Mysql如何查询某条记录在分页的第几页详析

    前言 在实践中我们会遇到这样的问题,知道某条记录的id,然后需要判断此条记录如果按照id进行排序分页,此条记录在第几页.今天这篇文章为大家提供一个思路. 下面话不多说了,来一起看看详细的实现方法吧 根据ID查询分页位置 根据ID来查询分页位置,比如按照ID的倒序排列,则可通过以下SQL查询出大于此ID记录数: select count(id) from user where id > 5; 示例中user为表名,5位待匹配的id.很显然,因为是倒序排序只需查找大于此id的记录数即可,如果是正序排

  • 浅谈mysql的子查询联合与in的效率

    最近的产品测试发现一个问题,当并发数量小于10时,响应时间可以维持在100毫秒以内.但是当并发数到达30个时,响应时间就超过1秒.这太不能接受了,要求是通过1秒中并发100个. 经过检测发现,时间主要是耗在其中的一个存储过程中.把存储过程的语句一条一条的过一遍也没有发现明显的不合理.因为mysql本身不能提供毫秒级别的时间,google了一个mysql的能提供毫秒的时间函数,再做测试,做了一个定位.发现是其中一条语句,语句是这个样子: select .... from A, B where ..

  • Mysql两表联合查询的四种情况总结

    一般来说,我们为了得到更完整的结果,我们需要从两个或更多的表中获取结果,我一般都是用select xxx,xxx from 表1,表2 where 表1.xxx=表2.xxx,我们一般都是进行的是这般的操作,其实mysql中还有一种操作,那就是join的操作,例如底下有两个表: 请看 "Persons" 表: 接下来请看 "Orders" 表: 以上的这两个表,然后我们把它们进行连接查询 SELECT Persons.LastName, Persons.FirstN

  • mysql使用from与join两表查询的区别总结

    前言 在mysql中,多表连接查询是很常见的需求,在使用多表查询时,可以from多个表,也可以使用join连接连个表 这两种查询有什么区别?哪种查询的效率更高呢? 带着这些疑问,决定动手试试 1.先在本地的mysql上先建两个表one和two one表 CREATE TABLE `one` ( `id` int(0) NOT NULL AUTO_INCREMENT, `one` varchar(100) NOT NULL, PRIMARY KEY (`id`) ) ENGINE = InnoDB

随机推荐