mysql中使用order by 和limit查询变慢解决办法

先来看一下测试性能

 代码如下 复制代码

1.显示行 0 - 9 (10 总计, 查询花费 32.4894 秒)  
2.SQL 查询: SELECT *  
3.FROM tables  
4.WHERE m_id  
5.IN ( 50, 49 )  
6.ORDER BY id DESC  
7.LIMIT 10  
显示行 0 - 9 (10 总计, 查询花费 32.4894 秒)
SQL 查询: SELECT *
FROM tables
WHERE m_id
IN ( 50, 49 )
ORDER BY id DESC
LIMIT 10

1.显示行 0 - 9 (10 总计, 查询花费 0.0497 秒)  
2.SQL 查询: SELECT *  
3.FROM tables  
4.WHERE m_id  
5.IN ( 50, 49 )  
6.LIMIT 10   
显示行 0 - 9 (10 总计, 查询花费 0.0497 秒)
SQL 查询: SELECT *
FROM tables
WHERE m_id
IN ( 50, 49 )
LIMIT 10

1.显示行 0 - 29 (1,333 总计, 查询花费 0.0068 秒)  
2.SQL 查询: SELECT *  
3.FROM tables  
4.WHERE m_id  
5.IN ( 50, 49 )  
6.ORDER BY id DESC  
7. 

显示行 0 - 29 (1,333 总计, 查询花费 0.0068 秒)
SQL 查询: SELECT *
FROM tables
WHERE m_id
IN ( 50, 49 )
ORDER BY id DESC

1.显示行 0 - 29 (1,333 总计, 查询花费 0.12秒)  
2.SQL 查询: SELECT *  
3.FROM tables  
4.WHERE m_id  
5.IN ( 50, 49 )  
6.ORDER BY m_id, id DESC  
7. 

显示行 0 - 29 (1,333 总计, 查询花费 0.12秒)
SQL 查询: SELECT *
FROM tables
WHERE m_id
IN ( 50, 49 )
ORDER BY m_id, id DESC

 

1.显示行 0 - 29 (1,333 总计, 查询花费 0.0068 秒)  
2.SQL 查询: SELECT *  
3.FROM tables  
4.FORCE INDEX ( m_id )     //强制索引  
5.WHERE m_id  
6.IN ( 50, 49 )  
7.ORDER BY id DESC  
8. 

上面的办法如果数据量上千万级也是会很慢的,有可能查询一次到10秒或更长,

优化limit和offset

MySQL的limit工作原理就是先读取n条记录,然后抛弃前n条,读m条想要的,所以n越大,性能会越差。
 

 代码如下 复制代码

优化前SQL: SELECT * FROM member ORDER BY last_active LIMIT 50,5
优化后SQL: SELECT * FROM member INNER JOIN (SELECT member_id FROM member ORDER BY last_active LIMIT

50, 5) USING (member_id)

分别在于,优化前的SQL需要更多I/O浪费,因为先读索引,再读数据,然后抛弃无需的行。而优化后的SQL(子查询

那条)只读索引(Cover index)就可以了,然后通过member_id读取需要的列。

对mysql服务器优化也可以提升性能了

1、只返回需要的数据

返回数据到客户端至少需要数据库提取数据、网络传输数据、客户端接收数据以及客户端处理数据等环节,如果返

回不需要的数据,就会增加服务器、网络和客户端的无效劳动,其害处是显而易见的,避免这类事件需要注意:

A、横向来看,不要写SELECT *的语句,而是选择你需要的字段。

B、纵向来看,合理写WHERE子句,不要写没有WHERE的SQL语句。

C、注意SELECT INTO后的WHERE子句,因为SELECT INTO把数据插入到临时表,这个过程会锁定一些系统表,如果这

个WHERE子句返回的数据过多或者速度太慢,会造成系统表长期锁定,诸塞其他进程。

D、对于聚合查询,可以用HAVING子句进一步限定返回的行。

2、尽量少做重复的工作

这一点和上一点的目的是一样的,就是尽量减少无效工作,但是这一点的侧重点在客户端程序,需要注意的如下:

A、控制同一语句的多次执行,特别是一些基础数据的多次执行是很多程序员很少注意的。

B、减少多次的数据转换,也许需要数据转换是设计的问题,但是减少次数是程序员可以做到的。

C、杜绝不必要的子查询和连接表,子查询在执行计划一般解释成外连接,多余的连接表带来额外的开销。

D、合并对同一表同一条件的多次UPDATE,比如

 代码如下 复制代码

UPDATE EMPLOYEE SET FNAME=’HAIWER’ WHERE EMP_ID=’ VPA30890F’

UPDATE EMPLOYEE SET LNAME=’YANG’ WHERE EMP_ID=’ VPA30890F’

这两个语句应该合并成以下一个语句

 代码如下 复制代码
UPDATE EMPLOYEE SET FNAME=’HAIWER’,LNAME=’YANG’ 
WHERE EMP_ID=’ VPA30890F’

E、UPDATE操作不要拆成DELETE操作+INSERT操作的形式,虽然功能相同,但是性能差别是很大的。

F、不要写一些没有意义的查询,比如: SELECT * FROM EMPLOYEE WHERE 1=2

3、注意事务和锁

事务是数据库应用中和重要的工具,它有原子性、一致性、隔离性、持久性这四个属性,很多操作我们都需要利用

事务来保证数据的正确性。在使用事务中我们需要做到尽量避免死锁、尽量减少阻塞。具体以下方面需要特别注意

A、事务操作过程要尽量小,能拆分的事务要拆分开来。

B、事务操作过程不应该有交互,因为交互等待的时候,事务并未结束,可能锁定了很多资源。

C、事务操作过程要按同一顺序访问对象。

D、提高事务中每个语句的效率,利用索引和其他方法提高每个语句的效率可以有效地减少整个事务的执行时间。

E、尽量不要指定锁类型和索引,SQL SERVER允许我们自己指定语句使用的锁类型和索引,但是一般情况下,SQL

SERVER优化器选择的锁类型和索引是在当前数据量和查询条件下是最优的,我们指定的可能只是在目前情况下更有

,但是数据量和数据分布在将来是会变化的。

F、查询时可以用较低的隔离级别,特别是报表查询的时候,可以选择最低的隔离级别

时间: 2024-07-29 06:53:49

mysql中使用order by 和limit查询变慢解决办法的相关文章

MySQL中max_allowed_packet设置过小导致记录写入失败的解决办法

mysql根据配置文件会限制server接受的数据包大小. 有时候大的插入和更新会受max_allowed_packet 参数限制,导致写入或者更新失败. 查看目前配置 show VARIABLES like '%max_allowed_packet%'; 显示的结果为: +--------------------+---------+ | Variable_name | Value | +--------------------+---------+ | max_allowed_packet

MYSQL中多对多关系的数据查询处理,请大神指点

问题描述 MYSQL中多对多关系的数据查询处理,请大神指点 用户表 create table user( uid int primary key auto_increment, uname varchar(30), uaddress varchar(15)) 订单表 create table orders( oid int primary key auto_increment, uid int not null, address varchar(70)); 商品表 create table pr

操作必须使用一个可更新的查询”错误的解决办法

  XP操作系统下出现"Microsoft OLE DB Provider for ODBC Drivers (0x80004005) 操作必须使用一个可更新的查询"错误的解决办法 1.在asp操作数据库时出现"操作必须使用一个可更新的查询"错误: 2.文件夹--〉属性;或,资源管理器--〉工具--〉文件夹选项 3.在"查看"选项卡中不钩选"使用简单文件共享" 4.这样,你在XP下NTFS分区文件夹右键,也能看到如WIN200

JPA 不在 persistence.xml 文件中配置每个Entity实体类的2种解决办法

原文:JPA 不在 persistence.xml 文件中配置每个Entity实体类的2种解决办法 在Spring 集成 Hibernate 的JPA方式中,需要在persistence配置文件中定义每一个实体类,这样非常地不方便,远哥目前找到了2种方法.   这2种方式都可以实现不用persistence.xml文件,免去每个Entity都要在persistence.xml文件中配置的烦恼,但是这种方式Entity实体类的主键字段注解@ID要放到 getXXX()方法上,否则不认.   方式1

后端接收不到AngularJs中$http.post发送的数据原因分析及解决办法_AngularJS

1.问题: 后端接收不到AngularJs中$http.post发送的数据,总是显示为null 示例代码: $http.post(/admin/KeyValue/GetListByPage, { pageindex: 1, pagesize: 8 }) .success(function(){ alert("Mr靖"); }); 代码没有错,但是在后台却接收不到数据,这是为什么呢? 用火狐监控:参数是JSON格式 用谷歌监控:传参方式是request payload 可以发现传参方式是

mysql导入sql文件过大或连接超时的解决办法

原文:mysql导入sql文件过大或连接超时的解决办法      前段时间出差在现场开发的时候,导入数据库老是出问题.最后发现了一个神奇sql语句交给实施,只要导入出错就把如下语句执行就可以了.至今屡试不爽. set global max_allowed_packet=100 000 000; set global net_buffer_length=100000; SET GLOBAL interactive_timeout=28800 000; SET GLOBAL wait_timeout

mysql中提高Order by语句查询效率的两个思路分析_Mysql

因为可能需要对数据库的记录进行重新排序.在这篇文章中,笔者就谈谈提高Order By语句查询效率的两个思路,以供大家参考. 在MySQL数据库中,Order by语句的使用频率是比较高的.但是众所周知,在使用这个语句时,往往会降低数据查询的性能.因为可能需要对数据库的记录进行重新排序.在这篇文章中,笔者就谈谈提高Order By语句查询效率的两个思路,以供大家参考. 498)this.width=498;" border=0>  一.建议使用一个索引来满足Order By子句. 在条件允许

MySQL中基本的多表连接查询教程_Mysql

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

MySQL中字符串与Num类型拼接报错的解决方法_Mysql

发现问题 图片地址如下 yun_qi_img/1473574486942944.jpg 需要实现的效果是要加上尺寸,如以下效果 yun_qi_img/1473574486942944.jpg|1200*675 一开始想当然使用 UPDATE tag_group SET cover = cover + '|1200*675' WHERE id = 1; 结果报错 Data truncation: Truncated incorrect DOUBLE value: 'yun_qi_img/14735