MySQL查询优化--细节理论
select的 high_priority还是比较有用,在实践中,平均5~6秒提高到3秒
=========================================================================
前面的部分主要是聚焦于如何让单独的查询执行的速度更快。MySQL还允许你改变语句调度的优 先级,它可以使来自多个客户端的查询更好地协作,这样单个客户端就不会由于锁定而等待很长时间。改变优先级还可以确保特定类型的查询被处理得更快。这一部 分讲解MySQL的默认的调度策略和可以用来影响这些策略的选项。它还谈到了并发性插入操作的使用和存储引擎锁定层次对客户端的并发性的影响。为了讨论的 方便,我们把执行检索(SELECT)的客户端称为"读取者",把执行修改操作(DELETE、INSERT、REPLACE或UPDATE)的客户端称 为"写入者"。
MySQL的默认的调度策略可用总结如下:
· 写入操作优先于读取操作。
· 对某张数据表的写入操作某一时刻只能发生一次,写入请求按照它们到达的次序来处理。
· 对某张数据表的多个读取操作可以同时地进行。
MyISAM和MEMORY存储引擎借助于数据表锁来实现这样的调度策略。当客户端访问某张表的时候,首先必须获取它的锁。当客户端完成对表的 操作的时候,锁就会被解除。通过LOCK TABLES和UNLOCK TABLES语句来显式地获取或释放锁是可行的,但是在通常情况下,服务器的锁管理器会自动地在需要的时候获取锁,在不再需要的时候释放锁。获取的锁的类 型依赖于客户端是写入还是读取操作。
对某张表进行写入操作的客户端必须拥有独占的(排他的)访问权的锁。操作在进行的过程中,该数据表处于不一致的(inconsistent)状 态,因为数据记录在删除、添加或修改的时候,数据表上的索引也可能需要更新以相互匹配。这个数据表在变化的过程中,如果允许其它的客户端访问,会出现问 题。非常明显,允许两个客户端同时写入一张数据表是不利的,因为这样的操作会很快使数据表中的信息成为一堆无用的垃圾。但是允许客户端读取变化之中的数据 表也不好,因为正在读取的位置中的数据可能正在变化(修改),读取的结果可能不是真实的。
对某张表执行读取操作的客户端必须获取一个锁,防止在读取的过程中,其它的客户端写入或改变表。但是这个锁不需要独占的访问权。读取操作不会改变数据,因此没有理由让某个读取者阻止其它的读取者访问这张表。因此读取锁允许其它的客户端在同一时刻读取这张表。
MySQL提供了几个语句调节符,允许你修改它的调度策略:
· LOW_PRIORITY关键字应用于DELETE、INSERT、LOAD DATA、REPLACE和UPDATE。
· HIGH_PRIORITY关键字应用于SELECT和INSERT语句。
· DELAYED关键字应用于INSERT和REPLACE语句。
LOW_PRIORITY和HIGH_PRIORITY调节符影响那些使用数据表锁的存储引擎(例如MyISAM和MEMORY)。DELAYED调节符作用于MyISAM和MEMORY数据表。
改变语句调度的优先级
LOW_PRIORITY关键字影响DELETE、INSERT、LOAD DATA、REPLACE和UPDATE语句的执行调度。通常情况下,某张数据表正在被读取的时候,如果有写入操作到达,那么写入者一直等待读取者完成操 作(查询开始之后就不能中断,因此允许读取者完成操作)。如果写入者正在等待的时候,另一个读取操作到达了,该读取操作也会被阻塞(block),因为默 认的调度策略是写入者优先于读取者。当第一个读取者完成操作的时候,写入者开始操作,并且直到该写入者完成操作,第二个读取者才开始操作。
如果写入操作是一个LOW_PRIORITY(低优先级)请求,那么系统就不会认为它的优先级高于读取操作。在这种情况下,如果写入者在等待的时候,第 二个读取者到达了,那么就允许第二个读取者插到写入者之前。只有在没有其它的读取者的时候,才允许写入者开始操作。理论上,这种调度修改暗示着,可能存在 LOW_PRIORITY写入操作永远被阻塞的情况。如果前面的读取操作在进行的过程中一直有其它的读取操作到达,那么新的请求都会插入到 LOW_PRIORITY写入操作之前。
SELECT查询的HIGH_PRIORITY(高优先级)关键字也类似。它允许 SELECT插入正在等待的写入操作之前,即使在正常情况下写入操作的优先级更高。另外一种影响是,高优先级的SELECT在正常的SELECT语句之前 执行,因为这些语句会被写入操作阻塞。
如果你希望所有支持LOW_PRIORITY选项的语句都默认地按照低优先级来处理,那么请使 用--low-priority-updates选项来启动服务器。通过使用INSERT HIGH_PRIORITY来把INSERT语句提高到正常的写入优先级,可以消除该选项对单个INSERT语句的影响。
使用延迟插入操作
DELAYED调节符应用于INSERT和REPLACE语句。当 DELAYED插入操作到达的时候,服务器把数据行放入一个队列中,并立即给客户端返回一个状态信息,这样客户端就可以在数据表被真正地插入记录之前继续 进行操作了。如果读取者从该数据表中读取数据,队列中的数据就会被保持着,直到没有读取者为止。接着服务器开始插入延迟数据行(delayed-row) 队列中的数据行。在插入操作的同时,服务器还要检查是否有新的读取请求到达和等待。如果有,延迟数据行队列就被挂起,允许读取者继续操作。当没有读取者的 时候,服务器再次开始插入延迟的数据行。这个过程一直进行,直到队列空了为止。
感觉上LOW_PRIORITY和DELAYED是相 似的,两者都允许数据行插入操作被延迟,但是它们对客户端操作的影响却有很大的差异。LOW_ PRIORITY强迫客户端等待,直到那些数据行可以被插入数据表。DELAYED允许客户端继续操作,服务器在内存中缓冲那些数据行,直到自己有时间处 理它们。
如果其它的客户端可能运行很长的SELECT语句并且你不希望阻塞,等待插入操作完成的时候,INSERTDELAYED就非常有用处了。客户端提交INSERT DELAYED的时候可能处理得很快,因为服务器只是简单地把要插入的数据行排队。
但是,你也必须知道正常的INSERT与INSERT DELAYED行为之间的一些其它的差异。如果INSERT DELAYED语句包含语法错误,客户端会得到一个错误,但是却无法得到其它一些在正常情况下可以使用的信息。例如,当语句返回的时候,你无法依赖(得 到)AUTO_INCREMENT(自动增长)值。同样,你无法得到唯一索引的副本数量。发生这种情况的原因在于插入操作在真正地被执行之前已经返回了状 态信息。另一种可能出现的情况是,由于INSERT DELAYED语句的数据行都在内存中排队,当服务器崩溃或者使用kill -9退出的时候,数据行可能丢失(正常情况下,kill -TERM终止命令不会导致这种情况,因为服务器在退出之前会把数据行插入表中)。
使用并发的插入操作
MyISAM存储引擎有一条例外的规则,它允许读取者阻塞写入者。这种现象发生在MyISAM数据表中间没有"空洞"(可能是删除或更新数据行的结果) 的情况下。当数据表没有"空洞"的时候,任何INSERT语句必然在末尾而不是中部添加数据行。在这种情况下,MySQL允许其它客户端在读取数据的同时 向数据表添加数据行。这就是"并发性插入操作",因为它们同时发生,检索并没有被阻塞。
如果你希望使用并发性插入操作,请注意下面一些事项:
· 在INSERT语句中不要使用LOW_PRIORITY调节符。它会引起INSERT经常被读取者阻塞,因此阻碍了并发性插入操作的执行。
· 如果读取者需要显式地锁定数据表以执行并发性插入操作,就应该使用LOCK TABLES ... READ LOCAL,而不是LOCK TABLES ... READ。LOCAL关键字会获取一个锁,允许并发性操作继续进行,因为它只能应用于数据表中已有的数据行,不会阻塞那些添加到末尾的新数据行。
· LOAD DATA操作应该使用CONCURRENT调节符,允许该数据表上的SELECT语句同时执行。
· 中间包含了"空洞"的MyISAM数据表不能使用并发性插入操作。但是,你可以使用OPTIMIZE TABLE语句来整理该数据表的碎片。
锁的层次和并发性
前面讨论的调度调节符允许你改变默认的调度策略。其中的大部分内容都是介绍使用这些调节符来解决数据表层次(table-level)的锁引起的问题,这都是MyISAM和MEMORY存储引擎用来管理数据表争用的问题的。
BDB和InnoDB存储引擎实现了不同层次的锁,所以其性能特征和对争用的管理是不同的。BDB引擎使用页面层次(page-level)的锁。 InnoDB引擎使用数据行层次(row-level)的锁,但是只在必要的时候使用(在很多情况下,例如当读取操作都完成的时候,InnoDB可能根本 就不使用锁)。
存储引擎使用的锁的层次对客户端的并发操作有很大的影响。假设两个客户端都希望更新某个数据表中的一行。由于要执行更 新,每个客户端都需要一个写入锁。对于MyISAM数据表,引擎会为第一个客户端分配一个锁,这会引起第二个客户端阻塞,直到第一个客户端完成操作。对于 BDB数据表,它可以实现更大的并发性:两个更新操作会同步进行,除非两个数据行都位于同一个页面中。在InnoDB数据表中,并发性更高;只要两个客户 端没有更新同一行,两个更新操作就能同时发生。
一般的规则是,锁的层次越细微,并发性越好,因为只要客户端使用数据表的部分不同,那么使用表的客户端就可以更多。它实际暗示着不同的存储引擎适合于不同的语句混合(mixes):
· MyISAM检索的速度非常快。但是使用表层次的锁可能成为混合的检索和更新环境中的问题,特别是检索倾向于长时间运行的时候。在这些条件下,更新可能需要等待很久才能进行。
· 当更新操作很多的时候,BDB和InnoDB数据表可以提供更好的性能。由于锁在页面或数据行层次进行,表被锁定的范围较小。这会减少锁的争用,提高并发性。
在防止死锁(deadlock)方面,表层次的锁比细微层次的锁更有优势。使用表层次的锁的时候,死锁不会发生。服务器可以通过查看语句来检测需要的数 据表,并提前锁定它们。而InnoDB和BDB数据表会发生死锁,因为这些存储引擎没有在事务开始的时候分配所有必要的锁。作为代替,在事务处理的过程 中,当检测到需要锁的时候才分配。这就可能出现两个语句获取了锁,接着试图进一步获取锁(需要多个锁),但是这些锁却被对方保持着,等待对方释放。其结果 是每个客户端都拥有一个锁,同时还需要利用其它的客户端拥有的锁才能继续执行。这会导致死锁,服务器必须终止其中一个事务。
==== 如何使用??? ===========================================
优先操作 HIGH_PRIORITY
HIGH_PRIORITY可以使用在select和insert操作中,让MYSQL知道,这个操作优先进行。
SELECT HIGH_PRIORITY * FROM TABLE1;
滞后操作 LOW_PRIORITY
LOW_PRIORITY可以使用在insert和update操作中,让mysql知道,这个操作滞后。
update LOW_PRIORITY table1 set field1= where field1= …
延时插入 INSERT DELAYED
INSERT DELAYED INTO table1 set field1= …
INSERT DELAYED INTO,是客户端提交数据给MySQL,MySQL返回OK状态给客户端。而这是并不是已经将数据插入表,而是存储在内存里面等待排队。当mysql有 空余时,再插入。另一个重要的好处是,来自许多客户端的插入被集中在一起,并被编写入一个块。这比执行许多独立的插入要快很多。坏处是,不能返回自动递增 的ID,以及系统崩溃时,MySQL还没有来得及插入数据的话,这些数据将会丢失。
http://blog.sina.com.cn/s/blog_4b45f83e0100e65n.html
MySQL查询优化--细节理论的更多相关文章
- Atitit Mysql查询优化器 存取类型 范围存取类型 索引存取类型 AND or的分析
Atitit Mysql查询优化器 存取类型 范围存取类型 索引存取类型 AND or的分析 Atitit Mysql查询优化器 存取类型 范围存取类型 索引存取类型 AND or的分析1 存 ...
- MySQL查询优化之explain的深入解析
在分析查询性能时,考虑EXPLAIN关键字同样很管用.EXPLAIN关键字一般放在SELECT查询语句的前面,用于描述MySQL如何执行查询操作.以及MySQL成功返回结果集需要执行的行数.expla ...
- 1025WHERE执行顺序以及MySQL查询优化器
转自http://blog.csdn.net/zhanyan_x/article/details/25294539 -- WHERE执行顺序-- 过滤比较多的放在前面,然后更加容易匹配,从左到右进行执 ...
- MySQL查询优化:查询慢原因和解决技巧
在开发的朋友特别是和mysql有接触的朋友会碰到有时mysql查询很慢,当然我指的是大数据量百万千万级了,不是几十条了,下面我们来看看解决查询慢的办法. MySQL查询优化:查询慢原因和解决方法 会经 ...
- mysql查询优化器为什么可能会选择错误的执行计划
有可能导致mysql优化器选择错误的执行计划的原因如下: A:统计信息不准确,mysql依赖存储引擎为其提供的统计信息来评估成本,然而有的存储引擎提供的信息是准确的,有的引擎提供的可能就偏差很大,如: ...
- Mysql查询优化器
Mysql查询优化器 本文的目的主要是通过告诉大家,查询优化器为我们做了那些工作,我们怎么做,才能使查询优化器对我们的sql进行优化,以及启示我们sql语句怎么写,才能更有效率.那么到底mysql到底 ...
- MySQL查询优化 (一)
以下的文章主要讲述的是MySQL查询优化的5个十分好用方法,熟悉SQL语句的人都清楚,如果要对一个任务进行操作的话,SQL语句可以有很多种相关写法,但是不同的写法查询的性能可能会有天壤之别. 本文列举 ...
- MySQL查询优化:连接查询排序limit
MySQL查询优化:连接查询排序limit(join.order by.limit语句) 2013-02-27 个评论 收藏 我要投稿 MySQL查询优化:连接查询排序 ...
- MySQL查询优化之explain
在分析查询性能时,考虑EXPLAIN关键字同样很管用.EXPLAIN关键字一般放在SELECT查询语句的前面,用于描述MySQL如何执行查询操作.以及MySQL成功返回结果集需要执行的行数.expla ...
随机推荐
- web前端开发分享-css,js入门篇(转)
转自:http://www.cnblogs.com/jikey/p/3600308.html 关注前端这么多年,没有大的成就,就入门期间积累了不少技巧与心得,跟大家分享一下,不一定都适合每个人,毕竟人 ...
- 十字链表 Codeforces Round #367 E Working routine
// 十字链表 Codeforces Round #367 E Working routine // 题意:给你一个矩阵,q次询问,每次交换两个子矩阵,问最后的矩阵 // 思路:暴力肯定不行.我们可以 ...
- XNA Game Studio 4.0 Programming 随便读,随便记 “Game Class”
XNA 中的 Game 类,是所有神奇事情发生的地方.几乎游戏中所有的事情都由它来操办. 它是项目中的王者,让我们深入窥探一番: 虚方法 Game 本身从众多其它地方继续了许多能力才能完成游戏中的事情 ...
- Spark中的编程模型
1. Spark中的基本概念 Application:基于Spark的用户程序,包含了一个driver program和集群中多个executor. Driver Program:运行Applicat ...
- CORBA
公共对象请求代理体系结构(Common Object Request Broker Architecture)
- arduino图形化编程——ardublock
下载地址:http://sourceforge.net/projects/ardublock/ 项目主页:https://github.com/taweili/ardublock 运行效果图 ardu ...
- VS2015创建的C++程序在Debug模式下不能调试
如题,不能调试的问题,解决办法: 1.修改工程属性页 2.修改VS2015托管兼容模式 工具->选项->调试,勾选使用托管兼容
- android 拍照或者图库选择 压缩后 图片 上传
通过拍照或者从相册里选择图片通过压缩并上传时很多应用的常用功能,记录一下实现过程 一:创建个临时文件夹用于保存压缩后需要上传的图片 /** * path:存放图片目录路径 */ private Str ...
- 利用red5搭建一个简单的流媒体直播系统
http://blog.sina.com.cn/s/blog_51396f890102exmz.html 一.red5安装.设置. 这个过程就不多说了,参见http://blog.csdn.net/l ...
- linux下登陆用户的行为信息—w和who命令详解
查看用户的操作系统管理员若想知道某一时刻用户的行为,只需要输入命令w 即可,在SHELL终端中输入如下命令: [root@localhost ~]# w 可以看到执行w命令及显示结果. 命令信息含义上 ...