高性能的MySQL(6)查询慢与重构查询

只有好的库表结构、合理的索引还不够,我们还需要合理的设计查询,齐头并进,一个不少才能充分发挥MySQL的优势。

一、查询为什么会慢?

每一个查询由一系列的子任务组成,每个子任务都会消耗一定的时间。这个我们在之前的单个查询分析时已经简单介绍了,当然还有额外的因素,比方说包括网络,CPU计算,统计信息,执行计划,锁等待等操作,或者底层引擎在调用内存,CPU操作,I/O操作等上的消耗时间。、

优化查询的目的就是减少和消除这些操作所花费的时间。

查询性能低下的最基本原因是访问的数据太多,大部分的性能低下的查询可以通过减少访问的数据量进行优化,一般有2个简单的分析方法:

1、确认应用程序是否返回了大量超过需要的数据,这就是说访问了太多的行,也有时候是因为访问了太多的列,这会增加很多额外的开销,包括,网络,CPU,内存等。

一些常见的例子:

a、查询不需要的记录

一个常见的错误是常常会以为MySQL会只返回需要的数据,实际上却是先返回全部的查询结果再进行计算,一个简单有效的解决方法是在查询后面加上LIMIT。

b、多表关联时返回全部列

比如,要查找所有在电影hreo中出现的演员,不要这样去写

select * from actor
inner join film_actor using(actor_id)
inner join film using(film_id)
where film.title = "hreo";

这会返回三个表的全部列,应该只返回需要的列

select actor.* from actor
inner join film_actor using(actor_id)
inner join film using(film_id)
where film.title = "hreo";

c、不要总是取出全部的列

select * from actor....

d、重复查询相同的数据

例如在用户评论的地方需要查询用户的头像,如果用户多次评论,可能会反复查询这个数据,可以先缓存起来,这样会更好。


2、确认MySQL服务层是否在返回前检索大量超过需要的数据行。

如果查询为了返回结果扫描过多的数据,那么就不合适了,一般看3个指标:

a、响应时间

响应时间分为服务时间和排队时间。这个很难细分,如果是在一个合理的值,那就可以接受。

b、扫描的行和返回的行

这个在一定程度上能够说明该查询找到需要的数据效率怎么样。理想的情况下,扫描的行和返回的行是相同的,不过实际中这是很难的,特别是做关联查询时。

c、扫描的行和访问类型

在explain语句中的type列反应了访问类型。从全表扫描到索引扫描,范围扫描,唯一索引查询,常数引用等,速度从慢到快,扫描的行从大到小。一般我们增加一个合适的索引就可以很高效了。

CREATE TABLE `emp5` (`id` int(11) NOT NULL DEFAULT '0',`name` varchar(100) NOT NULL,`job` varchar(100) NOT NULL,`num1` int(10) DEFAULT NULL,`num2` int(10) DEFAULT NULL,`num3` int(10) DEFAULT NULL,`job_num` int(10) DEFAULT NULL,`d` date DEFAULT NULL,PRIMARY KEY (`id`),KEY `job_num` (`job_num`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

174912329.png

这里说明使用了索引类型,如果去掉了索引

175032172.png

访问类型为全表扫描(ALL)

一般MySQL能够使用如下三种方式应用where,从好到坏依次是

a、在索引中使用where过滤不匹配的数据,引擎层完成。

b、使用索引覆盖扫描,在Extra中出现了Using index,直接从索引中过滤掉不需要的记录,服务层完成,不需回表取数据。

c、从数据表返回数据,然后过滤,在Extra中出现了Using where ,在服务层完成。


二、重构查询

一个复杂查询还是多个简单查询,是否需要将一个复杂的查询分成多个简单的查询,这是一个需要好好衡量的问题了。

1、切分查询

删除数据就是一个很好的例子。定期的清楚大量的数据,可能需要锁住大量的数据,占满整个事务,耗尽资源,阻塞很多小的查询,切分是一个很好的办法。

比方说:把如下的句子

delete from message where create_time < date_sub(now(),interval 3 month);

换成如下:

rows_affected=0
do{rows_affected = do_query("delete from message where create_time < date_sub(now(),interval 3 month limit 10000"))
}while rows_affected > 0

一次删除10000行,影响就会很小,压力就会分担开来了。

2、分解关联查询

把关联查询进行分解,例如下面的查询:

select * from tag
join tag_post on tag_post.tag_id = tag_id
join post on tag_post.post_id = post.id
where tag.tag = 'hreo';

分解为:

select * from tag where tag = 'hreo';
select * from tag_post where tag_id=1234;
select * from post where id in (123,546,432);

乍一看,我们好像复杂化了,但是分解后还是有很多好处的,有的时候我们的却是需要这样做的 。

a、让缓存的效率更高,如果第一个查询的结果已经缓存了,那么就可以跳过第一个查询,另外对一MySQL的查询缓存Query Cache来说,如果关联的表发生了修改,就无法使用缓存了,拆分后,那么一个表的改变不会影响其他表的缓存。

b、单个查询可以减少锁的竞争。

c、在应用层做关联,有更好的扩展性。

d、可以减少冗余记录的查询,因为数据库关联查询时,可能需要重复的访问一部分数据。

e、这个相当于实现了哈希关联,而不是MySQL的嵌套循环关联,某些时候哈希关联效率高很多,这点以后会有介绍。

这个效果,在负载均衡,或者数据分布在不同的数据库是更明显。







本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/461971.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

一道大小端题目

今天看到一道关于大小端的题目&#xff0c;觉得很有趣&#xff0c;理解一番后摘抄如下&#xff1a; 题目&#xff1a; 示意图&#xff1a; 结果说明&#xff1a; 小端模式 大端模式

算法复杂度速查表

图例 数据结构操作 数组排序算法 图操作 堆操作 大 O 复杂度图表 Big O 复杂度 推荐阅读 Cracking the Coding Interview: 150 Programming Questions and Solutions[33] Introduction to Algorithms, 3rd Edition[34] Data Structures and Algorithms in Java (2nd Edition)…

遇到异常:这可能是由某个扩展导致的

重构机房收费系统&#xff0c;我用EA画完UML图&#xff0c;打算用EA自己生成VB.NET代码&#xff0c;这样会方面些。没想到事情没有我想象的那么简单&#xff0c;可能是第一次尝试的原因&#xff0c;导入代码的过程中问题是一个接着一个。不过还好&#xff0c;虽然沿途困难重重&…

文件IO——文件IO相关概念

1、API &#xff08;1&#xff09;基于linux做应用开发&#xff0c;其实就是通过调用linux系统提供的API来实现。 &#xff08;2&#xff09;API 是一些由linux系统提供的函数&#xff0c;给应用层使用&#xff0c;以完成一定的功能。 &#xff08;3&#xff09;常用的文件IO的…

git使用小记

1. 基本操作 全局配置&#xff1a; git config --global user.name xx git config --global user.email xxx 初始化一个仓库&#xff1a; git init 添加&#xff1a; git add "file1.txt" git commit -m "添加文件1" 比较&#xff1a;分别列出每个文件…

LINUX内核之普通自旋锁

LINUX内核之普通自旋锁 CopyLeft by ICANTH&#xff0c;I Can do ANy THing that I CAN THink&#xff01;~ Author&#xff1a;WenHui&#xff0c;WuHan University&#xff0c;2012-6-15 PDF版阅读地址&#xff1a;http://www.docin.com/p1-424285718.html 普通自旋锁 自旋锁…

MFC COMBO-BOX最详细教程

找了好多&#xff0c;这是讲的最清楚的&#xff0c;与大家共享&#xff01; 转&#xff1a;https://blog.csdn.net/fym0121/article/details/7515862 当你只需从一列对象中选出一个时&#xff0c;使用COMBO BOX是一个好主意&#xff0c;因为它节省空间。这篇文章讲述了如何使…

uboot源码——主Makefile的分析

以下内容源于朱有鹏嵌入式课程的学习与整理&#xff0c;如有侵权请告知删除。 参考博客&#xff1a;u-boot Makefile完全解读_williamwang2013的博客-CSDN博客 参考博客&#xff1a;U-boot主Makefile分析_XiaoBaWu的博客-CSDN博客 参考博客&#xff1a;U-boot配置及编译阶段…

Designing Virtual Connect for vSphere 5.x

Designing Virtual Connect for vSphere 5.x如何在 HP C7000刀笼使用VC以满足vSphere 5.x 英文视频连接如下&#xff1a;http://professionalvmware.com/2013/05/vbrownbag-follow-up-designing-virtual-connect-for-vsphere-with-joe-clark-elgwhoppo/1&#xff1a;首先介绍一…

VMware vCenter Converter 关闭SSL加密,提高35-40%性能

VMware vCenter Converter 关闭SSL加密,提高35-40%性能原文&#xff1a;http://www.vmwarearena.com/2013/07/improving-transfer-rate-of-p2v-and-v2v.htmlVMware vCenter Converter Standalone 5.0 is a free tool from VMware to easily perform P2V(Physical to virtual co…

图像拼接算法及实现

第一章 绪论 1.1 图像拼接技术的研究背景及研究意义 图像拼接(image mosaic)是一个日益流行的研究领域&#xff0c;他已经成为照相绘图学、计算机视觉、图像处理和计算机图形学研究中的热点。图像拼接解决的问题一般式&#xff0c;通过对齐一系列空间重叠的图像&#xff0c;构…

程序员,你还在 Select * 吗?

应用程序慢如牛&#xff0c;原因多多&#xff0c;可能是网络的原因、可能是系统架构的原因&#xff0c;还有可能是数据库的原因。 那么如何提高数据库SQL语句执行速度呢&#xff1f;有人会说性能调优是数据库管理员&#xff08;DBA&#xff09;的事&#xff0c;然而性能调优跟程…

学习笔记-记ActiveMQ学习摘录与心得(二)

上个周末被我玩过去了&#xff0c;罪过罪过&#xff0c;现在又是一个工作日过去啦&#xff0c;居然有些烦躁&#xff0c;估计这几天看的东西有点杂&#xff0c;晚上坐下来把自己首要工作任务总结总结。上篇学习博客讲了ActiveMQ的特性及安装部署&#xff0c;下面先把我以前启动…

谈谈C#中的三个关键词new , virtual , override(装载 Winner.Net)

C#支持单继承&#xff0c;说到继承就不得不说new&#xff0c;virtual和override这三个关键词&#xff0c;灵活正确的使用这三个关键词&#xff0c;可以使程序结构更加清晰&#xff0c;代码重用性更高。 以下是msdn中对new&#xff0c;virtual和override的定义&#xff1a; …

unsigned char s1 : 2的用法

#include<stdio.h> #include<stdlib.h> //默认按照四字节对齐 //#pragma pack(1) union V {struct X{unsigned char s1 : 2;unsigned char s2 : 3;unsigned char s3 : 3;} x;unsigned char c; } v; //#pragma pack()int main(void) {v.c 100;//对应的二进制数字是…

juc线程池原理(六):jdk线程池中的设计模式

一、jdk中默认线程池中的代理模式 单例类线程池只有一个线程&#xff0c;无边界队列&#xff0c;适合cpu密集的运算。jdk中创建线程池是通过Executors类中提供的静态的方法来创建的&#xff0c;其中的单例类线程池的方法如下&#xff1a; public static ExecutorService newSin…

Code First :使用Entity. Framework编程(6) ----转发 收藏

Chapter6 Controlling Database Location,Creation Process, and Seed Data 第6章 控制数据库位置&#xff0c;创建过程和种子数据 In previous chapters you have seen how convention and configuration can be used to affect the model and the resulting database schema.…

计算多个文档之间的文本相似程度

首先我们上代码&#xff1a; from sklearn.feature_extraction.text import CountVectorizer corpus [ UNC played Duke in basketball, Duke lost the basketball game, I ate a sandwich ] vectorizer CountVectorizer(binaryTrue,stop_wordsenglish)#设置停用词为英语&…

双边滤波

双边滤波 高斯滤波是最常用的图像去噪方法之一&#xff0c;它能很好地滤除掉图像中随机出现的高斯噪声&#xff0c;但是在之前的博客中提到过&#xff0c;高斯滤波是一种低通滤波&#xff08;有兴趣的点击这里&#xff0c;查看之前的博客&#xff09;&#xff0c;它在滤除图像中…

用SQL语句更改数据库名,表名,列名

参考SQL Server联机丛书的 sp_renamedb与sp_rename一、更改数据库名sp_renamedb更改数据库的名称。语法sp_renamedb [ dbname ] old_name ,[ newname ] new_name 参数[ dbname ] old_name 是数据库的当前名称。old_name 为 sysname 类型&#xff0c;无默认值…