免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1401 | 回复: 0
打印 上一主题 下一主题

5.1 MySQL查询处理的基础知识 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2007-03-26 22:50 |只看该作者 |倒序浏览

从MySQL收到一个查询到发回查询结果给客户端所做的工作,是一个相对直观的过程。这些工作分解为几个独立的步骤,我们逐一了解一下这些步骤。
5.1.1 查询缓存(Query Cache)
你能够在my.cnf配置文件中为query_cache_type配置项(4.0.1之后的版本可用)设置一个合适的值,来打开查询缓存(Query
Cache):
query_cache_type = 1
MySQL会在分析和执行一个SELECT查询之前,先尝试在查询缓存中为此SELECT检索结果。MySQL是通过将查询语句进行哈希计算,将此哈希值作为从缓存中检索结果集的依据。MySQL严格的区分构成查询语句的文本,所以缓存对查询语句最细小的差别也是敏感的。
以目前所提到的缓存,这个查询:
SELECT * FROM table1
与下面的这个查询是不同的:
select * FROM table1
空格的不同也会造成同样的情况。MySQL不会截断查询语句开头和结尾的空格。这很少会成为一个问题,因为绝大多数情况下,查询语句都是由应用程序所生成,而不是通过人键盘手工输入的。
为了省点儿力气,MySQL做了一些取巧的工作。它只对SELECT查询进行哈希,因为其是唯一对缓存有意义的查询。不幸的是,4.0之前的MySQL版本不会考虑每个SELECT查询。它使用的逻辑是以大小写敏感的方式检查查询语句的前3个字母,只有SEL 才会被匹配。
这种基于3个字母的以管窥豹的结果,就是在你的查询语句的开头有空格或者其他任何非匹配的字符时,MySQL都不会使用查询缓存。在某些应用程序中这可能真的是个问题,我们遇到过在一个输送处理系统中,开发人员在每个查询语句的开头使用注释来签入额外的信息:
/* GetLatestStuff */ SELECT * FROM sometable WHERE ...
这个注释有助于在一个管理工具从SHOW PROCESSLIST的结果输出中标识每个查询,并将其显示在网页上。不幸的是,没有一种方式能告诉MySQL在确定一个语句是否是SELECT查询的时候“用点儿心”,所以上述的查询从来没有被缓存过。幸运的是,升级到MySQL 5.0 这个问题就不会再出现了。
不过告诉MySQL不要对某个查询进行缓存也是可能的。具体的回避查询缓存的方式就是在查询语句中加入SQL_NO_CACHE 的提示字。
SELECT SQL_NO_CACHE * FROM mytable
这有助于控制缓存污染。如果你的应用程序拥有一系列不能从缓存机制获得好处的查询语句,比如那些每周只运行一次的语句,对其进行缓存是没有意义的。告诉MySQL不要缓存这些语句,可以留出更多的空间为其他频繁执行的查询存储结果集。
当查询缓存以按需模式(Ondemand Mode)运行的时候(将my.cnf中的query_cache_type设置为2),MySQL就会在只有指定了SQL_CACHE 的情况下,才会尝试去缓存中查找查询。
SELECT SQL_CACHE * FROM mytable
如果一个查询对应的哈希值被查到,MySQL就会像所预期的那样,将缓存中的结果集直接发送到客户端,而跳过后续的处理。
查询缓存中的结果集的格式,与要发送到客户端的格式是一致的。所以从缓存中检索和发送结果集到客户端的开销是非常小的,MySQL只是简单的将数据直接发送到网络上。第六章中我们会探讨查询缓存的性能问题。
5.1.2 解析,分析和优化
在MySQL能够对一个非缓存的查询做任何有趣(或者有用)的事情之前,它必须将查询分析成不同的成份部分。作为处理过程的一部分,它首先要验证查询语句的语法有效性,并收集关于查询的一些基本信息:
·        
这是什么类型的查询?是一条SELECT, INSERT, UPDATE,
or DELETE语句,还是一些类似SET 和 GRANT的管理命令?
·        
涉及到哪些表?是否使用了什么别名?
·        
WHERE 子句是什么样的?
·        
有否包含其他的提示和修饰字?
一旦一个查询语句被分解为几个基本的片段,MySQL就开始了更具挑战性的工作-确定如何执行这个查询。这就查询优化器(Query Optimizer)的用武之地了。查询优化器的目标,简单说,就是从所有给定的可用信息中,找到执行查询最高效的路径。多数情况下,这意味着优化器不得不要缩小检查的记录的数量。这么做的目的是因为磁盘I/O所耗费的时间,在一个查询所花费的时间中经常(并非总是)居于统治地位。直觉上这是完全有道理的,可以作为我们之前讨论为什么索引如此有用的一个延伸。
关于优化器是如何做出判断的,对不熟悉MySQL内部机制的人来说,觉得就像一种魔法。当然,这绝对不是什么魔法。MySQL有一套从早期演化至今的规则和试探算法。这些规则支配着决策的过程。但是就像其他任何用于处理人类能够收集的数据并进行问题决策的应用程序一样,优化器并非是完美无缺的,它所使用那些规则和试探算法多数时候工作的非常好,但偶尔也有工作的不好的时候。
MySQL的开发者一直不停的在改进优化器-努力让其在新的版本中变得更加聪明和迅速。基于真实生产环境下的用户反馈,他们一直在寻找增强MySQL做出正确决策能力的途径。如果你发现一个查询导致MySQL作出了错误的决策,一定要报告给开发者。没有被报告的问题很少会得到修正。
为了作出更好的决策,MySQL会尝试回答以下几个重要的问题。
·        
是否存在可用的让记录的查找更快速的索引?
·        
哪个索引是最优的?如果涉及多个数据表,哪个索引对所有表而言是最优的?
·        
Join中哪些数据表如何依赖别的数据表?
·        
对多个数据表而言,最佳的Join顺序是怎样的?
当然,MySQl需要迅速的做出决策,而且不能逐一对所有的选项进行实际测试。否则它花在决定如何执行查询上的时间,会超过查询实际执行所需的时间!
MySQL大部分的优化努力,都是围绕索引和表的连接顺序(Join
Order)进行的。这些虽然不是唯一的影响因素,但它们的确是重要的因素之一。为更好的理解MySQL是如何决策一个SELECT 查询执行过程的,最好的方式就是查看该查询的EXPLAIN 输出。
5.1.3 使用 EXPLAIN 命令
那么,MySQL能够不费力气和时间收集的信息类型有哪几种呢?我们来看一些对新闻头条表的查询,这个表可以用来构建一个可定制的新闻网站。表结构列在下面。与其猜测MySQL可能会怎么做,我们不如直接使用深藏不露的EXPLAIN
命令来帮助揭示真相。如此一来,我们还会看到如何通过增加一个索引,或者简单的重新修改查询语句,来更好的利用一个现有的索引并极大的提高性能。
mysql> describe Headline;+------------+------------------+------+-----+---------+----------------+| Field      | Type             | Null | Key | Default | Extra          |+------------+------------------+------+-----+---------+----------------+| Id         | int(10) unsigned |      | PRI | NULL    | auto_increment || Headline   | varchar(255)     |      |     |         |                || Url        | varchar(255)     |      | UNI |         |                || Time       | int(10) unsigned |      | MUL | 0       |                || ExpireTime | int(10) unsigned |      |     | 0       |                || Date       | varchar(6)       |      |     |         |                || Summary    | text             | YES  |     | NULL    |                || ModTime    | timestamp        | YES  |     | NULL    |                |+------------+------------------+------+-----+---------+----------------+8 rows in set (0.00 sec)
就像你所看到的,Headline 表包含着新闻报道的信息:标题、概要、日期等等。头条可以与多个在Topic表中定义的话题(Topic)相关联。T2H 则映射主题与头条之间的关系。这是一个多对多的关系,因为单条的新闻可能被关联到多个话题。
当你针对主键或者唯一索引编写一个查询时,MySQL就会知道对每一个要匹配的值,最多有一条记录与之相对应。这个查询实际上执行起来也是非常之快。
mysql> SELECT Headline, Url FROM Headline WHERE Id = 13950120 \G*************************** 1. row ***************************Headline: Midwest Cash Grain PM - Soy off, USDA data awaited     Url: http://biz.yahoo.com/rm/030328/markets_grain_cash_2.html1 row in set (0.00 sec)
显而易见,MySQL知道只有一条记录能够匹配上。它查找记录的策略也是直接的:通过主键索引来检索。如果记录存在,则获取记录。为了验证,我们EXPLAIN 一下:
mysql> EXPLAIN SELECT Headline, Url FROM Headline WHERE id = 13950120 \G*************************** 1. row ***************************           id: 1  select_type: SIMPLE         table: Headline          type: constpossible_keys: PRIMARY          key: PRIMARY      key_len: 4          ref: const         rows: 1        Extra:1 row in set (0.00 sec)
不出所料,MySQL知道只存在一条可能会匹配的记录。rows的值告诉了我们这一点。但是,MySQL所给出的这些信息也并非总是完全可信,你稍后会看到一些这样的情况。
当然,EXPLAIN 给出的信息不仅仅局限于有多少条记录会与条件匹配。我们简要地看一下它所提供的信息:
id
查询中所涉及到的表的ID。EXPLAIN 会为查询中每个涉及到的表都产生一条输出记录。

select_type
这个表在一个大的查询中是什么角色?可能的值为SIMPLE, PRIMARY, UNION, DEPENDENT UNION, SUBSELECT, 和
DERIVED。当我们讨论更加复杂的查询时,就会搞清楚这些值的意义了。

table
MySQL将从中读取记录的表名。

type
MySQL使用那种类型的连接(Join)?在本例中,你看到的是const ,这是因为查询中查询的是常量值。其他可能的值为system, eq_ref, ref, range, index, 或者
ALL。我们将在本章后面关于“连接(Joins)”的段落中深入的讨论这个问题。

possible_keys
MySQL可以借助来在表中查找记录的索引的列表,没有的话显示NULL。

key
在检查了所有的可用的索引(列在possible_keys中)之后,MySQL最终决定采用的最优的索引的名字。

key_len
键值的长度(以字节为单位)。

ref
用来匹配键值的列或者值。

rows
MySQL认为满足查询条件所需要检查的记录数。如果你经常在一个表中增加或者删除记录,使用
ANALYZE TABLE 可以让MySQL更新索引状态,从而能够做出更好的估计。

Extra
MySQL想表达的其他与查询执行相关的额外信息。随后我们会看到一些例子。
Simple 类型的就像上面的例子一样。我们来看一下按照范围进行检索的情况。
mysql> SELECT Url FROM Headline WHERE id BETWEEN 13950120 AND 13950125;+----------------------------------------------------------+| Url                                                      |+----------------------------------------------------------+| http://biz.yahoo.com/rm/030328/markets_grain_cash_2.html || http://biz.yahoo.com/prnews/030328/cgf038_1.html         || http://biz.yahoo.com/bw/030328/285487_1.html             || http://biz.yahoo.com/rc/030328/turkey_hijack_5.html      || http://biz.yahoo.com/rm/030328/food_aid_iraq_1.html      |+----------------------------------------------------------+5 rows in set (0.00 sec) mysql> EXPLAIN SELECT Url FROM Headline WHERE id BETWEEN 13950120 AND 13950125 \G*************************** 1. row ***************************           id: 1  select_type: SIMPLE        table: Headline         type: rangepossible_keys: PRIMARY          key: PRIMARY      key_len: 4          ref: NULL         rows: 3        Extra: Using where1 row in set (0.00 sec)
在本例中,type 从const 变成了 range ,说明这个查询是检索一个以上的值。同样的ref 的值变成了NULL。
如果仔细查看,你发现并非所有的事情都是合情合理的:当查询执行完成后,返回了5条记录,而rows 却说只有3条。这是因为rows 的输出纯粹是一个估计。或许将其称为estimated_rows 会更加准确。
这个估计是基于MySQL所使用的索引。基于记录在可能的键值上的分布,它简单的估计在13950120 与 13950125之间,存在3条有效的记录。
另外还要注意Extra 列显示Using where。这是MySQL再次重申它使用WHERE 子句所限定的记录集中选取记录。这个信息没有显示在之前的那个例子中,因为MySQL将使用主键来检索单行记录视为一个特例。
来看一下当我们基于一个未被索引的列来检索数据时的情况:
mysql> SELECT COUNT(*) FROM Headline WHERE ExpireTime >= 1112201600;+----------+| COUNT(*) |+----------+|     3971 |+----------+1 row in set (1.04 sec) mysql> EXPLAIN SELECT COUNT(*) FROM Headline WHERE ExpireTime >= 1112201600 \G*************************** 1. row ***************************           id: 1  select_type: SIMPLE        table: Headline         type: ALLpossible_keys: NULL          key: NULL      key_len: NULL          ref: NULL         rows: 302116        Extra: Using where1 row in set (0.00 sec)

EXPLAIN 的输出中,key 列显示的NULL值告诉我们,MySQL在此查询中不会使用任何索引。实际上,possible_keys列显示的NULL值告诉我们,根本也没有任何索引可用。如果这种查询在你的应用程序中是一个常见的查询,我们可以简单的增加一个索引,然后重新运行(或者EXPLAIN)这个查询,来验证MySQL是否使用了它。
mysql> ALTER TABLE Headline ADD INDEX (ExpireTime);Query OK, 302116 rows affected (40.02 sec)Records: 302116  Duplicates: 0  Warnings: 0 mysql> SELECT COUNT(*) FROM Headline WHERE ExpireTime >= 1112201600;+----------+| COUNT(*) |+----------+|     3971 |+----------+1 row in set (0.01 sec) mysql> EXPLAIN SELECT COUNT(*) FROM Headline WHERE ExpireTime >= 1112201600 \G*************************** 1. row ***************************           id: 1  select_type: SIMPLE        table: Headline         type: rangepossible_keys: ExpireTime          key: ExpireTime      key_len: 4          ref: NULL         rows: 12009        Extra: Using where; Using index1 row in set (0.00 sec)
这次查询的运行时间时0.01秒,而不是之前的1.04秒。EXPLAIN的输出看起来好多了,一个借助ExpireTime索引的range搜索。再次提醒注意实际返回记录行数(3791)与rows列所提示的值(12009)之间的不一致。在这种情况下,通过对Headline表运行ANALYZE TABLE或者OPTIMIZE TABLE命令,可能会提升MySQL估算的准确性。
另外,注意MySQL还提示了Using index。这表示这是一个纯粹基于索引(index-only)的查询。MySQL可以从ExpireTime 索引中得到所有要查询的数据,而不用在从磁盘上获取其他的记录信息。
但是当你确切的知道多条标题新闻的ID,并想获取它们时该如何做呢?你可能会使用OR 或者 IN(...)关键字?让我们来搞清楚MySQL是怎么做的,我们使用一个最小、一个最大和一个居中的标题新闻的ID值来进行查询:
mysql> SELECT Url FROM Headline WHERE Id IN(1531513, 10231599, 13962322);+----------------------------------------------+| Url                                          |+----------------------------------------------+| http://biz.yahoo.com/bond/010117/bf.html     || http://biz.yahoo.com/e/021101/yhoo10-q.html  || http://biz.yahoo.com/bw/030331/315850_1.html |+----------------------------------------------+3 rows in set (0.00 sec) mysql> EXPLAIN SELECT Url FROM Headline WHERE Id IN(1531513, 10231599, 13962322) \G*************************** 1. row ***************************           id: 1  select_type: SIMPLE        table: Headline         type: rangepossible_keys: PRIMARY          key: PRIMARY      key_len: 4          ref: NULL         rows: 3        Extra: Using where1 row in set (0.00 sec) mysql> SELECT Url FROM Headline WHERE Id = 1531513 OR Id = 10231599 OR Id = 13962322;+----------------------------------------------+| Url                                          |+----------------------------------------------+| http://biz.yahoo.com/bond/010117/bf.html     || http://biz.yahoo.com/e/021101/yhoo10-q.html  || http://biz.yahoo.com/bw/030331/315850_1.html |+----------------------------------------------+3 rows in set (0.03 sec) mysql> EXPLAIN SELECT Url FROM Headline WHERE Id = 1531513 OR Id = 10231599 OR Id = 13962322 \G*************************** 1. row ***************************           id: 1  select_type: SIMPLE        table: Headline         type: rangepossible_keys: PRIMARY          key: PRIMARY      key_len: 4          ref: NULL         rows: 3        Extra: Using where1 row in set (0.00 sec)
两个查询语句执行起来都非常的快,而且它们的EXPLAIN输出也是相同的。就功能上而言这是两个相同的操作。显然每个查询都只能返回0到3条记录。我们是基于一个唯一索引(主键)在进行查询,所以MySQL没有什么好考虑的。实际上,我们知道在这种情况下,MySQL内部是将多个OR查询条件转换成一个单一的IN(...)列表。然而,显然随着要检索的ID数量的增加,使用IN(..)会让查询语句的文本更短。而更短的查询语句也意味这更少的分析开销和更好的性能。
那么当我们使用一个子查询来获取ID最大的标题新闻URL时,又是一种什么情况呢?
mysql> EXPLAIN SELECT Url FROM Headline WHERE Id IN (SELECT MAX(Id) FROM Headline);
在等待了5分钟之后,我们强行中断了这个查询。嗯,要么是我们做错了什么,要么是MySQL没有使用更直观的途径来执行这个查询。嗯…
为了查明原因,我们EXPLAIN一下:
mysql> EXPLAIN SELECT Url FROM Headline WHERE Id IN (SELECT MAX(id) FROM Headline) \G*************************** 1. row ***************************           id: 1  select_type: PRIMARY        table: Headline         type: ALLpossible_keys: NULL          key: NULL      key_len: NULL          ref: NULL         rows: 302116        Extra: Using where*************************** 2. row ***************************           id: 2  select_type: DEPENDENT SUBSELECT        table: Headline         type: indexpossible_keys: NULL          key: PRIMARY      key_len: 4          ref: NULL         rows: 302116        Extra: Using index2 rows in set (0.00 sec)
呀!
MySQL没有使用索引!注意在上面输出的信息中两个possible_keys字段都是NULL。这是个BUG吗?或许是,除非当你认为在DEPENDENT SUBSELECT中key字段所显示的是基于主键进行查找。但是possible_keys并未提到主键索引可用。并且,更糟糕的是MySQL认为它必须检查302,116条记录才能完成这个基于主键的单行查询。
当然,这个测试是基于MySQL 4.1.0 alpha版本,在这个预发布的版本中,查询优化器并未针对更有效的处理子查询而进行调优。
[1]
此处的观点并非是说MySQL不知道如何正确的做事情,而是表达无论你如何的调优,MySQL偶尔还是会做出差劲的决策。当这种情况发生时,你需要能够诊断出问题所在,同时,在某些情况下,还需要提出解决方案。
[1]后续基于4.1.1 alhpa版本的测试证实,查询优化器的这个Bug得到了解决。
所以让我们重新组织一下查询语句来将事情简单化。我们使用在查询中使用IN(...)来返回唯一一条记录。这次我们将查询条件改变为一个相等逻辑(=)检查:
mysql> SELECT Url FROM Headline WHERE Id = (SELECT MAX(id) FROM Headline);+----------------------------------------------+| Url                                          |+----------------------------------------------+| http://biz.yahoo.com/bw/030331/315850_1.html |+----------------------------------------------+1 row in set (0.00 sec) mysql> EXPLAIN SELECT Url FROM Headline WHERE Id = (SELECT MAX(id) FROM Headline) \G*************************** 1. row ***************************           id: 1  select_type: PRIMARY        table: Headline         type: constpossible_keys: PRIMARY          key: PRIMARY      key_len: 4          ref: const         rows: 1        Extra:*************************** 2. row ***************************           id: 2  select_type: SUBSELECT        table: NULL         type: NULLpossible_keys: NULL          key: NULL      key_len: NULL          ref: NULL         rows: NULL        Extra: Select tables optimized away2 rows in set (0.00 sec)
A-ha! That did it. The query ran in a split
second.
啊哈!成功了。这个查询瞬间就完成了。
EXPLAIN的输出也很有意思。MySQL注意到了我们在进行一个微不足道的操作,从而将对第二次表查询优化掉了。所有的NULL是MySQL的一种表达方式:“这些开销微不足道”。
但是如果上面修改还不起作用呢?或者我们正在使用一个不支持子查询的MySQL的旧版本,这该怎么办呢。简单。我们可以将这个查询重新改写为两个SELECT语句,并且将中间值存在一个服务端的变量中,这样就无需在客户端进行状态维护了:
mysql> SELECT @max := MAX(Id) FROM Headline;+-----------------+| @max := MAX(Id) |+-----------------+|        13962322 |+-----------------+1 row in set (0.00 sec) mysql> SELECT Url FROM Headline WHERE Id = @max;+----------------------------------------------+| Url                                          |+----------------------------------------------+| http://biz.yahoo.com/bw/030331/315850_1.html |+----------------------------------------------+1 row in set (0.00 sec)
我们甚至都不用EXPLAIN这两个查询。基于我们目前所了解的,这两个查询显然会执行的非常快(实际情况也的确如此)。每条查询都是基于主键检索单个值。
同时,为完整起见,给出一种最符合MySQL风格的编写这个查询的方式,就是使用ORDER
BY 和 LIMIT关键字:
SELECT Url FROM Headline ORDER BY Id DESC LIMIT 1;
我们来看最后一个例子。基于两个不同的被索引的字段进行查询会是一种什么情况?MySQL会尝试选择能够产生更小的检验结果集的索引。所以最终的情况取决于你的数据以及用于检索的值。
mysql> SELECT COUNT(*) FROM Headline WHERE ExpireTime >= 1112201600 AND Id 5000000;+----------+| COUNT(*) |+----------+|     1175 |+----------+1 row in set (0.04 sec) mysql> EXPLAIN SELECT COUNT(*) FROM Headline    -> WHERE ExpireTime >= 1112201600 AND Id *************************** 1. row ***************************           id: 1  select_type: SIMPLE        table: Headline         type: rangepossible_keys: PRIMARY,ExpireTime          key: ExpireTime      key_len: 4          ref: NULL         rows: 12009        Extra: Using where1 row in set (0.00 sec)
对于这次查询来说,有主键字段(Id)和索引字段(ExpireTime)可供选择。MySQL最终选择了ExpireTime。然而,如果ExpireTime值变成会匹配到更多候选记录的值,MySQL就会偏向使用主键:
mysql> EXPLAIN SELECT COUNT(*) FROM Headline WHERE ExpireTime >= 1012201600 AND Id 5000000 \G*************************** 1. row ***************************           id: 1  select_type: SIMPLE        table: Headline         type: rangepossible_keys: PRIMARY,ExpireTime          key: PRIMARY      key_len: 4          ref: NULL         rows: 13174        Extra: Using where1 row in set (0.00 sec)
不出所料,MySQL就是这么做的。
再强调一下,这个决策过程完全取决于MySQL对于数据当前状况的意识,这种意识指的就是值分布的平均程度。不同的存储引擎(InnoDB,MyISAM,BDB)使用不同的方法来收集这些统计信息。因此你会发现同样的查询,在你将改变数据表的存储类型之后,执行速度存在差别。当然,执行ANALYZE TABLE也会影响到MySQL的统计。
5.1.3.1 连接(Joins)
当你查询多个表的时候,事情开始变得稍微有些复杂。MySQL必须确定什么样的执行顺序最优的。重申一下优化的目标,就是了尽可能少的读取数据记录,所以MySQL就会考察每张表,并估算必须从其种读取的行数。为了达到这个目标,MySQL还必须清除这几个表之间存在的关系。举个例子,在下面的查询种,MySQL就不能首先读order表:
SELECT customer.name, order.date_placed, region.nameFROM customer, order, regionWHERE order.customer_id = customer.idAND customer.region_id = region.idAND customer.name = 'John Doe'
MySQL要从order表中检索的记录,依赖于customer表。所以它必须在读order表之前先读customer表。同样的,region也是依赖于customer表。在本例中,MySQL就是先从customer表中先读取记录的。此后,它就可以自由的决定以什么顺序从余下的表中读取数据。
不幸的是,找到优化的连接顺序,是MySQL最弱的能力之一。MySQL不是去尝试更加聪明的解决问题,而是简单采用了一种暴力手段来解决问题。在做出选择之前,MySQL尝试所有可能的组合。某些情况下,这种方式会带来灾难。我们见过至少一个例子,其中MySQL花费了29秒的时间去确定如何执行一个多连接的查询,然后只花1秒钟就真正的执行完了这个查询。在这种特殊情况下,涉及到了10张表。因为MySQL要尝试所有的优化组合,在表的数量超过少量几个时,查询性能会急剧下降。当然,表的数量准确值取决于当前CPU的运算能力。
5.1.4 执行( Execution)
之前没有过多的提到查询的执行。MySQL简单的按照查询计划,逐个的从每张表中获取行,然后基于相关列(但愿存在索引)建立连接。在这个过程中,有可能需要创建一个临时表(在内存或者磁盘上),来保存结果集,一旦所有的结果集都可用,就发送给客户端。
如果查询执行时间超过了服务器所设定的阈值,并且在日志选项被打开的情况下,上述信息会被记录在慢速查询日志(Slow Query Log)中(本章后面会讨论)。如果查询是以交互的方式进行的(比如通过mysql命令行),上述信息也会出现在查询结果中。
在这个过程中,MySQL还会从每个被执行的查询收集一些信息和统计项目:
·        
谁请求的这个查询
·        
查询处理花费了多长时间
·        
返回了多少行数据
  如果查询执行时间超过了服务器所设定的阈值,并且在日志选项被打开的情况下,上述信息会被记录在慢速查询日志(Slow Query Log)中(本章后面会讨论)。如果查询是以交互的方式进行的(比如通过mysql命令行),上述信息也会出现在查询结果中。
               
               
               

本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u/7114/showart_265444.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP